qontract-reconcile 0.10.1rc879__py3-none-any.whl → 0.10.1rc894__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.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/RECORD +291 -284
- reconcile/acs_rbac.py +1 -2
- reconcile/aus/advanced_upgrade_service.py +14 -14
- reconcile/aus/aus_label_source.py +1 -2
- reconcile/aus/base.py +23 -26
- reconcile/aus/cluster_version_data.py +4 -4
- reconcile/aus/models.py +2 -3
- reconcile/aus/version_gate_approver.py +2 -6
- reconcile/aus/version_gates/__init__.py +1 -3
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
- reconcile/aws_account_manager/integration.py +9 -14
- reconcile/aws_account_manager/reconciler.py +51 -1
- reconcile/aws_account_manager/utils.py +3 -0
- reconcile/aws_ami_cleanup/integration.py +3 -4
- reconcile/aws_iam_password_reset.py +2 -5
- reconcile/aws_version_sync/integration.py +2 -2
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/approver.py +4 -5
- reconcile/change_owners/bundle.py +20 -22
- reconcile/change_owners/change_types.py +23 -24
- reconcile/change_owners/changes.py +13 -16
- reconcile/change_owners/decision.py +2 -5
- reconcile/change_owners/diff.py +11 -15
- reconcile/change_owners/self_service_roles.py +1 -2
- reconcile/change_owners/tester.py +7 -10
- reconcile/checkpoint.py +2 -5
- reconcile/cli.py +26 -12
- reconcile/closedbox_endpoint_monitoring_base.py +8 -11
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +2 -5
- reconcile/dashdotdb_base.py +8 -11
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +10 -14
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +5 -8
- reconcile/database_access_manager.py +5 -6
- reconcile/dynatrace_token_provider/integration.py +3 -6
- reconcile/dynatrace_token_provider/integration_v2.py +20 -0
- reconcile/dynatrace_token_provider/meta.py +1 -0
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +4 -4
- reconcile/external_resources/model.py +3 -3
- reconcile/external_resources/secrets_sync.py +5 -5
- reconcile/external_resources/state.py +5 -5
- reconcile/gabi_authorized_users.py +3 -6
- reconcile/gcr_mirror.py +1 -1
- reconcile/github_org.py +1 -3
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_housekeeping.py +7 -11
- reconcile/gitlab_labeler.py +1 -2
- reconcile/gitlab_members.py +2 -5
- reconcile/gitlab_permissions.py +1 -3
- reconcile/glitchtip/integration.py +5 -8
- reconcile/glitchtip_project_alerts/integration.py +57 -33
- reconcile/glitchtip_project_dsn/integration.py +8 -11
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +6 -0
- reconcile/gql_definitions/fragments/aws_account_managed.py +8 -0
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +4 -4
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +27 -7
- reconcile/integrations_manager.py +5 -8
- reconcile/jenkins/types.py +5 -6
- reconcile/jenkins_job_builder.py +9 -12
- reconcile/jenkins_roles.py +1 -1
- reconcile/jira_watcher.py +2 -2
- reconcile/ldap_groups/integration.py +2 -5
- reconcile/ocm/types.py +21 -26
- reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
- reconcile/ocm_clusters.py +8 -8
- reconcile/ocm_internal_notifications/integration.py +1 -2
- reconcile/ocm_labels/integration.py +2 -5
- reconcile/ocm_machine_pools.py +11 -15
- reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
- reconcile/openshift_base.py +29 -30
- reconcile/openshift_groups.py +15 -20
- reconcile/openshift_namespace_labels.py +8 -14
- reconcile/openshift_namespaces.py +5 -8
- reconcile/openshift_network_policies.py +2 -4
- reconcile/openshift_resources_base.py +19 -29
- reconcile/openshift_saas_deploy.py +9 -10
- reconcile/openshift_saas_deploy_change_tester.py +7 -10
- reconcile/openshift_saas_deploy_trigger_base.py +4 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_tekton_resources.py +7 -11
- reconcile/openshift_upgrade_watcher.py +10 -13
- reconcile/openshift_users.py +8 -11
- reconcile/oum/base.py +3 -4
- reconcile/oum/labelset.py +1 -2
- reconcile/oum/metrics.py +2 -2
- reconcile/oum/models.py +1 -2
- reconcile/oum/standalone.py +2 -3
- reconcile/prometheus_rules_tester/integration.py +6 -9
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +12 -13
- reconcile/quay_mirror_org.py +10 -10
- reconcile/queries.py +4 -7
- reconcile/resource_scraper.py +3 -4
- reconcile/rhidp/common.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +5 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
- reconcile/saas_auto_promotions_manager/publisher.py +5 -6
- reconcile/saas_auto_promotions_manager/subscriber.py +36 -15
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +8 -0
- reconcile/saas_file_validator.py +2 -5
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +3 -6
- reconcile/skupper_network/models.py +3 -5
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +15 -17
- reconcile/sql_query.py +5 -9
- reconcile/status_board.py +4 -5
- reconcile/statuspage/atlassian.py +14 -15
- reconcile/statuspage/integrations/maintenances.py +3 -3
- reconcile/statuspage/page.py +8 -8
- reconcile/statuspage/state.py +4 -5
- reconcile/statuspage/status.py +7 -8
- reconcile/templating/lib/rendering.py +8 -8
- reconcile/templating/renderer.py +10 -11
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +3 -6
- reconcile/terraform_cloudflare_dns.py +9 -12
- reconcile/terraform_cloudflare_resources.py +9 -11
- reconcile/terraform_cloudflare_users.py +8 -11
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +11 -14
- reconcile/terraform_resources.py +20 -21
- reconcile/terraform_tgw_attachments.py +32 -36
- reconcile/terraform_users.py +6 -7
- reconcile/terraform_vpc_resources/integration.py +6 -6
- reconcile/test/conftest.py +7 -10
- reconcile/test/fixtures.py +1 -1
- reconcile/test/saas_auto_promotions_manager/conftest.py +3 -2
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
- reconcile/test/test_database_access_manager.py +3 -6
- reconcile/test/test_gitlab_labeler.py +2 -5
- reconcile/test/test_jump_host.py +5 -8
- reconcile/test/test_ocm_machine_pools.py +1 -4
- reconcile/test/test_openshift_base.py +3 -6
- reconcile/test/test_openshift_cluster_bots.py +5 -5
- reconcile/test/test_openshift_namespace_labels.py +2 -3
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
- reconcile/test/test_saasherder.py +9 -12
- reconcile/test/test_slack_base.py +4 -6
- reconcile/test/test_status_board.py +4 -7
- reconcile/test/test_terraform_tgw_attachments.py +14 -20
- reconcile/typed_queries/alerting_services_settings.py +1 -2
- reconcile/typed_queries/app_interface_custom_messages.py +2 -3
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
- reconcile/typed_queries/app_interface_repo_url.py +1 -2
- reconcile/typed_queries/app_interface_state_settings.py +1 -3
- reconcile/typed_queries/app_interface_vault_settings.py +1 -2
- reconcile/typed_queries/aws_vpc_requests.py +1 -3
- reconcile/typed_queries/aws_vpcs.py +1 -3
- reconcile/typed_queries/clusters.py +2 -4
- reconcile/typed_queries/clusters_minimal.py +1 -3
- reconcile/typed_queries/clusters_with_dms.py +1 -3
- reconcile/typed_queries/dynatrace_environments.py +14 -0
- reconcile/typed_queries/external_resources.py +3 -4
- reconcile/typed_queries/pagerduty_instances.py +1 -2
- reconcile/typed_queries/repos.py +2 -3
- reconcile/typed_queries/reserved_networks.py +1 -3
- reconcile/typed_queries/saas_files.py +49 -59
- reconcile/typed_queries/slo_documents.py +1 -3
- reconcile/typed_queries/status_board.py +3 -7
- reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
- reconcile/typed_queries/terraform_namespaces.py +1 -2
- reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
- reconcile/utils/acs/base.py +2 -3
- reconcile/utils/acs/notifiers.py +3 -3
- reconcile/utils/acs/policies.py +3 -3
- reconcile/utils/aggregated_list.py +1 -1
- reconcile/utils/amtool.py +1 -2
- reconcile/utils/aws_api.py +28 -31
- reconcile/utils/aws_api_typed/account.py +23 -0
- reconcile/utils/aws_api_typed/api.py +20 -9
- reconcile/utils/binary.py +1 -3
- reconcile/utils/clusterhealth/providerbase.py +1 -2
- reconcile/utils/clusterhealth/telemeter.py +2 -2
- reconcile/utils/deadmanssnitch_api.py +1 -2
- reconcile/utils/disabled_integrations.py +4 -6
- reconcile/utils/environ.py +1 -1
- reconcile/utils/expiration.py +3 -7
- reconcile/utils/external_resource_spec.py +3 -4
- reconcile/utils/external_resources.py +4 -7
- reconcile/utils/filtering.py +1 -2
- reconcile/utils/git.py +3 -9
- reconcile/utils/git_secrets.py +5 -5
- reconcile/utils/github_api.py +5 -9
- reconcile/utils/gitlab_api.py +2 -3
- reconcile/utils/glitchtip/client.py +2 -4
- reconcile/utils/glitchtip/models.py +8 -11
- reconcile/utils/gql.py +26 -35
- reconcile/utils/grouping.py +1 -3
- reconcile/utils/imap_client.py +2 -5
- reconcile/utils/internal_groups/client.py +1 -2
- reconcile/utils/internal_groups/models.py +8 -9
- reconcile/utils/jenkins_api.py +4 -4
- reconcile/utils/jinja2/extensions.py +1 -1
- reconcile/utils/jinja2/filters.py +4 -4
- reconcile/utils/jinja2/utils.py +16 -16
- reconcile/utils/jira_client.py +10 -11
- reconcile/utils/jjb_client.py +14 -17
- reconcile/utils/jobcontroller/controller.py +5 -5
- reconcile/utils/jobcontroller/models.py +2 -2
- reconcile/utils/jsonpath.py +4 -5
- reconcile/utils/jump_host.py +7 -8
- reconcile/utils/keycloak.py +3 -7
- reconcile/utils/ldap_client.py +2 -3
- reconcile/utils/lean_terraform_client.py +13 -17
- reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
- reconcile/utils/membershipsources/models.py +19 -22
- reconcile/utils/metrics.py +13 -15
- reconcile/utils/mr/base.py +7 -11
- reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +1 -2
- reconcile/utils/oc.py +38 -38
- reconcile/utils/oc_connection_parameters.py +24 -25
- reconcile/utils/oc_filters.py +2 -3
- reconcile/utils/oc_map.py +9 -15
- reconcile/utils/ocm/addons.py +7 -10
- reconcile/utils/ocm/base.py +38 -39
- reconcile/utils/ocm/clusters.py +6 -9
- reconcile/utils/ocm/label_sources.py +1 -2
- reconcile/utils/ocm/labels.py +3 -6
- reconcile/utils/ocm/ocm.py +11 -14
- reconcile/utils/ocm/products.py +1 -3
- reconcile/utils/ocm/search_filters.py +16 -17
- reconcile/utils/ocm/service_log.py +2 -3
- reconcile/utils/ocm/sre_capability_labels.py +4 -8
- reconcile/utils/ocm/subscriptions.py +1 -3
- reconcile/utils/ocm/syncsets.py +2 -4
- reconcile/utils/ocm/upgrades.py +5 -9
- reconcile/utils/ocm_base_client.py +13 -16
- reconcile/utils/openshift_resource.py +5 -11
- reconcile/utils/output.py +2 -3
- reconcile/utils/pagerduty_api.py +4 -5
- reconcile/utils/prometheus.py +2 -2
- reconcile/utils/promotion_state.py +4 -5
- reconcile/utils/promtool.py +2 -8
- reconcile/utils/quay_api.py +12 -22
- reconcile/utils/raw_github_api.py +3 -5
- reconcile/utils/rosa/rosa_cli.py +6 -6
- reconcile/utils/rosa/session.py +6 -7
- reconcile/utils/runtime/desired_state_diff.py +3 -8
- reconcile/utils/runtime/environment.py +4 -7
- reconcile/utils/runtime/integration.py +4 -4
- reconcile/utils/runtime/meta.py +1 -2
- reconcile/utils/runtime/runner.py +7 -10
- reconcile/utils/runtime/sharding.py +22 -27
- reconcile/utils/saasherder/interfaces.py +63 -69
- reconcile/utils/saasherder/models.py +30 -35
- reconcile/utils/saasherder/saasherder.py +39 -54
- reconcile/utils/secret_reader.py +17 -19
- reconcile/utils/slack_api.py +15 -17
- reconcile/utils/smtp_client.py +1 -2
- reconcile/utils/sqs_gateway.py +1 -3
- reconcile/utils/state.py +1 -2
- reconcile/utils/terraform/config_client.py +4 -5
- reconcile/utils/terraform_client.py +12 -8
- reconcile/utils/terrascript/cloudflare_client.py +4 -10
- reconcile/utils/terrascript/cloudflare_resources.py +10 -13
- reconcile/utils/terrascript/models.py +2 -3
- reconcile/utils/terrascript/resources.py +1 -2
- reconcile/utils/terrascript_aws_client.py +50 -38
- reconcile/utils/unleash/client.py +4 -7
- reconcile/utils/unleash/server.py +2 -2
- reconcile/utils/vault.py +8 -11
- reconcile/utils/vaultsecretref.py +2 -3
- reconcile/utils/vcs.py +7 -8
- reconcile/vault_replication.py +4 -8
- reconcile/vpc_peerings_validator.py +4 -9
- release/version.py +6 -7
- tools/app_interface_reporter.py +2 -2
- tools/cli_commands/gpg_encrypt.py +3 -6
- tools/cli_commands/systems_and_tools.py +4 -7
- tools/qontract_cli.py +105 -17
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +105 -0
- tools/template_validation.py +1 -1
- tools/test/conftest.py +45 -6
- tools/test/test_saas_promotion_state.py +187 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/top_level.txt +0 -0
reconcile/github_org.py
CHANGED
@@ -438,9 +438,7 @@ def run(dry_run):
|
|
438
438
|
|
439
439
|
assert (
|
440
440
|
current_orgs == desired_orgs
|
441
|
-
), "Current orgs ({}) don't match desired orgs ({})"
|
442
|
-
current_orgs, desired_orgs
|
443
|
-
)
|
441
|
+
), f"Current orgs ({current_orgs}) don't match desired orgs ({desired_orgs})"
|
444
442
|
|
445
443
|
# Calculate diff
|
446
444
|
diff = current_state.diff(desired_state)
|
reconcile/github_repo_invites.py
CHANGED
@@ -5,10 +5,7 @@ from collections.abc import (
|
|
5
5
|
Mapping,
|
6
6
|
)
|
7
7
|
from dataclasses import dataclass
|
8
|
-
from typing import
|
9
|
-
Any,
|
10
|
-
Optional,
|
11
|
-
)
|
8
|
+
from typing import Any
|
12
9
|
|
13
10
|
from reconcile import queries
|
14
11
|
from reconcile.utils import (
|
@@ -27,7 +24,7 @@ class CodeComponents:
|
|
27
24
|
|
28
25
|
|
29
26
|
def _parse_code_components(
|
30
|
-
raw:
|
27
|
+
raw: Iterable[Mapping[str, Any]] | None,
|
31
28
|
) -> CodeComponents:
|
32
29
|
urls = set()
|
33
30
|
known_orgs = set()
|
reconcile/gitlab_housekeeping.py
CHANGED
@@ -9,11 +9,7 @@ from datetime import (
|
|
9
9
|
timedelta,
|
10
10
|
)
|
11
11
|
from operator import itemgetter
|
12
|
-
from typing import
|
13
|
-
Any,
|
14
|
-
Optional,
|
15
|
-
Union,
|
16
|
-
)
|
12
|
+
from typing import Any
|
17
13
|
|
18
14
|
import gitlab
|
19
15
|
from gitlab.v4.objects import (
|
@@ -178,7 +174,7 @@ def close_item(
|
|
178
174
|
gl: GitLabApi,
|
179
175
|
enable_closing: bool,
|
180
176
|
item_type: str,
|
181
|
-
item:
|
177
|
+
item: ProjectIssue | ProjectMergeRequest,
|
182
178
|
):
|
183
179
|
if enable_closing:
|
184
180
|
logging.info([
|
@@ -239,7 +235,7 @@ def handle_stale_items(
|
|
239
235
|
cancel_notes = [
|
240
236
|
n
|
241
237
|
for n in item.notes.list()
|
242
|
-
if n.attributes.get("body") == "/{} cancel"
|
238
|
+
if n.attributes.get("body") == f"/{LABEL} cancel"
|
243
239
|
]
|
244
240
|
if not cancel_notes:
|
245
241
|
continue
|
@@ -280,7 +276,7 @@ def is_rebased(mr, gl: GitLabApi) -> bool:
|
|
280
276
|
def get_merge_requests(
|
281
277
|
dry_run: bool,
|
282
278
|
gl: GitLabApi,
|
283
|
-
users_allowed_to_label:
|
279
|
+
users_allowed_to_label: Iterable[str] | None = None,
|
284
280
|
) -> list[dict[str, Any]]:
|
285
281
|
mrs = gl.get_merge_requests(state=MRState.OPENED)
|
286
282
|
return preprocess_merge_requests(
|
@@ -295,7 +291,7 @@ def preprocess_merge_requests(
|
|
295
291
|
dry_run: bool,
|
296
292
|
gl: GitLabApi,
|
297
293
|
project_merge_requests: list[ProjectMergeRequest],
|
298
|
-
users_allowed_to_label:
|
294
|
+
users_allowed_to_label: Iterable[str] | None = None,
|
299
295
|
) -> list[dict[str, Any]]:
|
300
296
|
results = []
|
301
297
|
for mr in project_merge_requests:
|
@@ -434,7 +430,7 @@ def rebase_merge_requests(
|
|
434
430
|
rebases += 1
|
435
431
|
rebased_merge_requests.labels(mr.target_project_id).inc()
|
436
432
|
except gitlab.exceptions.GitlabMRRebaseError as e:
|
437
|
-
logging.error("unable to rebase {}: {}"
|
433
|
+
logging.error(f"unable to rebase {mr.iid}: {e}")
|
438
434
|
else:
|
439
435
|
logging.info([
|
440
436
|
"rebase",
|
@@ -538,7 +534,7 @@ def merge_merge_requests(
|
|
538
534
|
return
|
539
535
|
merges += 1
|
540
536
|
except gitlab.exceptions.GitlabMRClosedError as e:
|
541
|
-
logging.error("unable to merge {}: {}"
|
537
|
+
logging.error(f"unable to merge {mr.iid}: {e}")
|
542
538
|
|
543
539
|
|
544
540
|
def get_app_sre_usernames(gl: GitLabApi) -> set[str]:
|
reconcile/gitlab_labeler.py
CHANGED
@@ -4,7 +4,6 @@ from collections.abc import (
|
|
4
4
|
Iterable,
|
5
5
|
Set,
|
6
6
|
)
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from reconcile import queries
|
10
9
|
from reconcile.gitlab_housekeeping import (
|
@@ -48,7 +47,7 @@ def get_parents_list() -> set[str]:
|
|
48
47
|
|
49
48
|
def guess_onboarding_status(
|
50
49
|
changed_paths: Iterable[str], apps: dict[str, dict], parent_apps: set[str]
|
51
|
-
) ->
|
50
|
+
) -> str | None:
|
52
51
|
"""
|
53
52
|
Guess the service name of a given MR from the changed paths of the
|
54
53
|
MR. This will allow to add the onboarding status to the MR's as label
|
reconcile/gitlab_members.py
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
import enum
|
2
2
|
import logging
|
3
3
|
from collections.abc import Callable
|
4
|
-
from typing import
|
5
|
-
Any,
|
6
|
-
Optional,
|
7
|
-
)
|
4
|
+
from typing import Any
|
8
5
|
|
9
6
|
from pydantic import BaseModel
|
10
7
|
|
@@ -203,7 +200,7 @@ def get_gitlab_instance(query_func: Callable) -> GitlabInstanceV1:
|
|
203
200
|
@defer
|
204
201
|
def run(
|
205
202
|
dry_run: bool,
|
206
|
-
defer:
|
203
|
+
defer: Callable | None = None,
|
207
204
|
) -> None:
|
208
205
|
gqlapi = gql.get_api()
|
209
206
|
# queries
|
reconcile/gitlab_permissions.py
CHANGED
@@ -21,9 +21,7 @@ def get_members_to_add(repo, gl, app_sre):
|
|
21
21
|
if maintainers is None:
|
22
22
|
return []
|
23
23
|
if gl.user.username not in maintainers:
|
24
|
-
logging.error(
|
25
|
-
"'{}' is not shared with {} as 'Maintainer'".format(repo, gl.user.username)
|
26
|
-
)
|
24
|
+
logging.error(f"'{repo}' is not shared with {gl.user.username} as 'Maintainer'")
|
27
25
|
return []
|
28
26
|
members_to_add = [
|
29
27
|
{"user": u, "repo": repo} for u in app_sre if u.username not in maintainers
|
@@ -3,10 +3,7 @@ from collections.abc import (
|
|
3
3
|
Iterable,
|
4
4
|
Sequence,
|
5
5
|
)
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
|
11
8
|
from reconcile.glitchtip.reconciler import GlitchtipReconciler
|
12
9
|
from reconcile.gql_definitions.glitchtip.glitchtip_instance import (
|
@@ -19,7 +16,7 @@ from reconcile.gql_definitions.glitchtip.glitchtip_project import (
|
|
19
16
|
DEFINITION as GLITCHTIP_PROJECT_DEFINITION,
|
20
17
|
)
|
21
18
|
from reconcile.gql_definitions.glitchtip.glitchtip_project import (
|
22
|
-
|
19
|
+
GlitchtipProjectV1,
|
23
20
|
RoleV1,
|
24
21
|
)
|
25
22
|
from reconcile.gql_definitions.glitchtip.glitchtip_project import (
|
@@ -87,7 +84,7 @@ def fetch_current_state(
|
|
87
84
|
|
88
85
|
|
89
86
|
def fetch_desired_state(
|
90
|
-
glitchtip_projects: Sequence[
|
87
|
+
glitchtip_projects: Sequence[GlitchtipProjectV1],
|
91
88
|
mail_domain: str,
|
92
89
|
internal_groups_client: InternalGroupsClient,
|
93
90
|
) -> list[Organization]:
|
@@ -143,7 +140,7 @@ def fetch_desired_state(
|
|
143
140
|
return list(organizations.values())
|
144
141
|
|
145
142
|
|
146
|
-
def get_glitchtip_projects(query_func: Callable) -> list[
|
143
|
+
def get_glitchtip_projects(query_func: Callable) -> list[GlitchtipProjectV1]:
|
147
144
|
glitchtip_projects = (
|
148
145
|
glitchtip_project_query(query_func=query_func).glitchtip_projects or []
|
149
146
|
)
|
@@ -172,7 +169,7 @@ def get_internal_groups_client(
|
|
172
169
|
|
173
170
|
@defer
|
174
171
|
def run(
|
175
|
-
dry_run: bool, instance:
|
172
|
+
dry_run: bool, instance: str | None = None, defer: Callable | None = None
|
176
173
|
) -> None:
|
177
174
|
gqlapi = gql.get_api()
|
178
175
|
vault_settings = get_app_interface_vault_settings()
|
@@ -4,10 +4,7 @@ from collections.abc import (
|
|
4
4
|
Callable,
|
5
5
|
Iterable,
|
6
6
|
)
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
)
|
7
|
+
from typing import Any
|
11
8
|
from urllib.parse import urlencode
|
12
9
|
|
13
10
|
from reconcile import jira_permissions_validator
|
@@ -18,7 +15,7 @@ from reconcile.gql_definitions.glitchtip_project_alerts.glitchtip_project import
|
|
18
15
|
GlitchtipProjectAlertRecipientEmailV1,
|
19
16
|
GlitchtipProjectAlertRecipientV1,
|
20
17
|
GlitchtipProjectAlertRecipientWebhookV1,
|
21
|
-
|
18
|
+
GlitchtipProjectV1,
|
22
19
|
)
|
23
20
|
from reconcile.gql_definitions.glitchtip_project_alerts.glitchtip_project import (
|
24
21
|
query as glitchtip_project_query,
|
@@ -46,7 +43,7 @@ ProjectStates = dict[str, Project]
|
|
46
43
|
|
47
44
|
|
48
45
|
class GlitchtipProjectAlertsIntegrationParams(PydanticRunParams):
|
49
|
-
instance:
|
46
|
+
instance: str | None = None
|
50
47
|
|
51
48
|
|
52
49
|
def webhook_urls_are_unique(alerts: Iterable[ProjectAlert]) -> bool:
|
@@ -70,10 +67,10 @@ class GlitchtipProjectAlertsIntegration(
|
|
70
67
|
def name(self) -> str:
|
71
68
|
return QONTRACT_INTEGRATION
|
72
69
|
|
73
|
-
def get_early_exit_desired_state(self) ->
|
70
|
+
def get_early_exit_desired_state(self) -> dict[str, Any] | None:
|
74
71
|
return {"projects": [c.dict() for c in self.get_projects(gql.get_api().query)]}
|
75
72
|
|
76
|
-
def get_projects(self, query_func: Callable) -> list[
|
73
|
+
def get_projects(self, query_func: Callable) -> list[GlitchtipProjectV1]:
|
77
74
|
return glitchtip_project_query(query_func=query_func).glitchtip_projects or []
|
78
75
|
|
79
76
|
def _build_project_alert_recipient(
|
@@ -95,7 +92,7 @@ class GlitchtipProjectAlertsIntegration(
|
|
95
92
|
|
96
93
|
def fetch_desired_state(
|
97
94
|
self,
|
98
|
-
glitchtip_projects: Iterable[
|
95
|
+
glitchtip_projects: Iterable[GlitchtipProjectV1],
|
99
96
|
gjb_alert_url: str | None,
|
100
97
|
gjb_token: str | None,
|
101
98
|
) -> list[Organization]:
|
@@ -123,30 +120,16 @@ class GlitchtipProjectAlertsIntegration(
|
|
123
120
|
)
|
124
121
|
)
|
125
122
|
if glitchtip_project.jira and gjb_alert_url:
|
126
|
-
|
127
|
-
if
|
128
|
-
|
129
|
-
elif (
|
130
|
-
glitchtip_project.jira.board
|
131
|
-
and integration_is_enabled(
|
132
|
-
QONTRACT_INTEGRATION, glitchtip_project.jira.board
|
133
|
-
)
|
134
|
-
and integration_is_enabled(
|
135
|
-
jira_permissions_validator.QONTRACT_INTEGRATION,
|
136
|
-
glitchtip_project.jira.board,
|
137
|
-
)
|
138
|
-
):
|
139
|
-
jira_project_key = glitchtip_project.jira.board.name
|
123
|
+
params: dict[str, str | list[str]] = {}
|
124
|
+
token_params = {"token": gjb_token} if gjb_token else {}
|
125
|
+
alert_labels = glitchtip_project.jira.labels or []
|
140
126
|
|
141
|
-
if
|
142
|
-
params
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
url = (
|
148
|
-
f"{gjb_alert_url}/{jira_project_key}?{urlencode(params, True)}"
|
149
|
-
)
|
127
|
+
if glitchtip_project.jira.project:
|
128
|
+
params = {
|
129
|
+
"labels": alert_labels,
|
130
|
+
"components": glitchtip_project.jira.components or [],
|
131
|
+
} | token_params
|
132
|
+
url = f"{gjb_alert_url}/{glitchtip_project.jira.project}?{urlencode(params, True)}"
|
150
133
|
alerts.append(
|
151
134
|
ProjectAlert(
|
152
135
|
name=GJB_ALERT_NAME,
|
@@ -160,6 +143,47 @@ class GlitchtipProjectAlertsIntegration(
|
|
160
143
|
],
|
161
144
|
)
|
162
145
|
)
|
146
|
+
|
147
|
+
elif (
|
148
|
+
glitchtip_project.jira.escalation_policy
|
149
|
+
and glitchtip_project.jira.escalation_policy.channels.jira_board
|
150
|
+
):
|
151
|
+
# definition via escalation policy
|
152
|
+
channels = glitchtip_project.jira.escalation_policy.channels
|
153
|
+
for board in channels.jira_board:
|
154
|
+
if not integration_is_enabled(
|
155
|
+
QONTRACT_INTEGRATION, board
|
156
|
+
) or not integration_is_enabled(
|
157
|
+
jira_permissions_validator.QONTRACT_INTEGRATION, board
|
158
|
+
):
|
159
|
+
continue
|
160
|
+
params = {
|
161
|
+
"labels": alert_labels + (channels.jira_labels or []),
|
162
|
+
"components": [channels.jira_component]
|
163
|
+
if channels.jira_component
|
164
|
+
else [],
|
165
|
+
} | token_params
|
166
|
+
if board.issue_type:
|
167
|
+
params["issue_type"] = board.issue_type
|
168
|
+
url = f"{gjb_alert_url}/{board.name}?{urlencode(params, True)}"
|
169
|
+
alerts.append(
|
170
|
+
ProjectAlert(
|
171
|
+
name=GJB_ALERT_NAME,
|
172
|
+
timespan_minutes=1,
|
173
|
+
quantity=1,
|
174
|
+
recipients=[
|
175
|
+
ProjectAlertRecipient(
|
176
|
+
recipient_type=RecipientType.WEBHOOK,
|
177
|
+
url=url,
|
178
|
+
)
|
179
|
+
],
|
180
|
+
)
|
181
|
+
)
|
182
|
+
else:
|
183
|
+
raise ValueError(
|
184
|
+
"Jira integration requires either project or escalation policy to be set"
|
185
|
+
)
|
186
|
+
|
163
187
|
# check for duplicates
|
164
188
|
if not webhook_urls_are_unique(alerts):
|
165
189
|
raise ValueError(
|
@@ -264,7 +288,7 @@ class GlitchtipProjectAlertsIntegration(
|
|
264
288
|
glitchtip_instances = glitchtip_instance_query(
|
265
289
|
query_func=gqlapi.query
|
266
290
|
).instances
|
267
|
-
glitchtip_projects_by_instance: dict[str, list[
|
291
|
+
glitchtip_projects_by_instance: dict[str, list[GlitchtipProjectV1]] = (
|
268
292
|
defaultdict(list)
|
269
293
|
)
|
270
294
|
for glitchtip_project in self.get_projects(query_func=gqlapi.query):
|
@@ -3,10 +3,7 @@ from collections.abc import (
|
|
3
3
|
Callable,
|
4
4
|
Iterable,
|
5
5
|
)
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
|
11
8
|
from sretoolbox.utils import threaded
|
12
9
|
|
@@ -20,7 +17,7 @@ from reconcile.gql_definitions.glitchtip.glitchtip_instance import (
|
|
20
17
|
from reconcile.gql_definitions.glitchtip.glitchtip_project import (
|
21
18
|
DEFINITION as GLITCHTIP_PROJECT_DEFINITION,
|
22
19
|
)
|
23
|
-
from reconcile.gql_definitions.glitchtip.glitchtip_project import
|
20
|
+
from reconcile.gql_definitions.glitchtip.glitchtip_project import GlitchtipProjectV1
|
24
21
|
from reconcile.gql_definitions.glitchtip.glitchtip_project import (
|
25
22
|
query as glitchtip_project_query,
|
26
23
|
)
|
@@ -73,7 +70,7 @@ def glitchtip_project_dsn_secret(project: Project, key: ProjectKey) -> dict[str,
|
|
73
70
|
|
74
71
|
|
75
72
|
def fetch_current_state(
|
76
|
-
project:
|
73
|
+
project: GlitchtipProjectV1,
|
77
74
|
oc_map: OCMap,
|
78
75
|
ri: ResourceInventory,
|
79
76
|
) -> None:
|
@@ -110,7 +107,7 @@ def fetch_current_state(
|
|
110
107
|
|
111
108
|
|
112
109
|
def fetch_desired_state(
|
113
|
-
glitchtip_projects: Iterable[
|
110
|
+
glitchtip_projects: Iterable[GlitchtipProjectV1],
|
114
111
|
ri: ResourceInventory,
|
115
112
|
glitchtip_client: GlitchtipClient,
|
116
113
|
) -> None:
|
@@ -145,7 +142,7 @@ def fetch_desired_state(
|
|
145
142
|
)
|
146
143
|
|
147
144
|
|
148
|
-
def projects_query(query_func: Callable) -> list[
|
145
|
+
def projects_query(query_func: Callable) -> list[GlitchtipProjectV1]:
|
149
146
|
glitchtip_projects = []
|
150
147
|
for project in (
|
151
148
|
glitchtip_project_query(query_func=query_func).glitchtip_projects or []
|
@@ -169,10 +166,10 @@ def projects_query(query_func: Callable) -> list[GlitchtipProjectsV1]:
|
|
169
166
|
def run(
|
170
167
|
dry_run: bool,
|
171
168
|
thread_pool_size: int = 10,
|
172
|
-
internal:
|
169
|
+
internal: bool | None = None,
|
173
170
|
use_jump_host: bool = True,
|
174
|
-
instance:
|
175
|
-
defer:
|
171
|
+
instance: str | None = None,
|
172
|
+
defer: Callable | None = None,
|
176
173
|
) -> None:
|
177
174
|
# settings
|
178
175
|
vault_settings = get_app_interface_vault_settings()
|
@@ -40,6 +40,13 @@ class AWSQuotaLimitsV1(ConfiguredBaseModel):
|
|
40
40
|
quotas: list[AWSQuotaV1] = Field(..., alias="quotas")
|
41
41
|
|
42
42
|
|
43
|
+
class AWSContactV1(ConfiguredBaseModel):
|
44
|
+
name: str = Field(..., alias="name")
|
45
|
+
title: Optional[str] = Field(..., alias="title")
|
46
|
+
email: str = Field(..., alias="email")
|
47
|
+
phone_number: str = Field(..., alias="phoneNumber")
|
48
|
+
|
49
|
+
|
43
50
|
class AWSAccountManaged(ConfiguredBaseModel):
|
44
51
|
name: str = Field(..., alias="name")
|
45
52
|
uid: str = Field(..., alias="uid")
|
@@ -47,3 +54,4 @@ class AWSAccountManaged(ConfiguredBaseModel):
|
|
47
54
|
premium_support: bool = Field(..., alias="premiumSupport")
|
48
55
|
organization: Optional[AWSOrganizationV1] = Field(..., alias="organization")
|
49
56
|
quota_limits: Optional[list[AWSQuotaLimitsV1]] = Field(..., alias="quotaLimits")
|
57
|
+
security_contact: Optional[AWSContactV1] = Field(..., alias="securityContact")
|
@@ -143,7 +143,7 @@ class GlitchtipInstanceV1(ConfiguredBaseModel):
|
|
143
143
|
name: str = Field(..., alias="name")
|
144
144
|
|
145
145
|
|
146
|
-
class
|
146
|
+
class GlitchtipProjectV1_GlitchtipOrganizationV1(ConfiguredBaseModel):
|
147
147
|
name: str = Field(..., alias="name")
|
148
148
|
instance: GlitchtipInstanceV1 = Field(..., alias="instance")
|
149
149
|
owners: Optional[list[str]] = Field(..., alias="owners")
|
@@ -180,19 +180,19 @@ class AppV1(ConfiguredBaseModel):
|
|
180
180
|
path: str = Field(..., alias="path")
|
181
181
|
|
182
182
|
|
183
|
-
class
|
183
|
+
class GlitchtipProjectV1(ConfiguredBaseModel):
|
184
184
|
name: str = Field(..., alias="name")
|
185
185
|
platform: str = Field(..., alias="platform")
|
186
186
|
project_id: Optional[str] = Field(..., alias="projectId")
|
187
187
|
event_throttle_rate: Optional[int] = Field(..., alias="eventThrottleRate")
|
188
188
|
teams: list[GlitchtipTeamV1] = Field(..., alias="teams")
|
189
|
-
organization:
|
189
|
+
organization: GlitchtipProjectV1_GlitchtipOrganizationV1 = Field(..., alias="organization")
|
190
190
|
namespaces: list[NamespaceV1] = Field(..., alias="namespaces")
|
191
191
|
app: Optional[AppV1] = Field(..., alias="app")
|
192
192
|
|
193
193
|
|
194
194
|
class ProjectsQueryData(ConfiguredBaseModel):
|
195
|
-
glitchtip_projects: Optional[list[
|
195
|
+
glitchtip_projects: Optional[list[GlitchtipProjectV1]] = Field(..., alias="glitchtip_projects")
|
196
196
|
|
197
197
|
|
198
198
|
def query(query_func: Callable, **kwargs: Any) -> ProjectsQueryData:
|
@@ -58,10 +58,18 @@ query GlitchtipProjectsWithAlerts {
|
|
58
58
|
}
|
59
59
|
jira {
|
60
60
|
project
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
components
|
62
|
+
escalationPolicy {
|
63
|
+
channels {
|
64
|
+
jiraBoard {
|
65
|
+
name
|
66
|
+
issueType
|
67
|
+
disable {
|
68
|
+
integrations
|
69
|
+
}
|
70
|
+
}
|
71
|
+
jiraComponent
|
72
|
+
jiraLabels
|
65
73
|
}
|
66
74
|
}
|
67
75
|
labels
|
@@ -113,16 +121,28 @@ class DisableJiraBoardAutomationsV1(ConfiguredBaseModel):
|
|
113
121
|
|
114
122
|
class JiraBoardV1(ConfiguredBaseModel):
|
115
123
|
name: str = Field(..., alias="name")
|
124
|
+
issue_type: Optional[str] = Field(..., alias="issueType")
|
116
125
|
disable: Optional[DisableJiraBoardAutomationsV1] = Field(..., alias="disable")
|
117
126
|
|
118
127
|
|
128
|
+
class AppEscalationPolicyChannelsV1(ConfiguredBaseModel):
|
129
|
+
jira_board: list[JiraBoardV1] = Field(..., alias="jiraBoard")
|
130
|
+
jira_component: Optional[str] = Field(..., alias="jiraComponent")
|
131
|
+
jira_labels: Optional[list[str]] = Field(..., alias="jiraLabels")
|
132
|
+
|
133
|
+
|
134
|
+
class AppEscalationPolicyV1(ConfiguredBaseModel):
|
135
|
+
channels: AppEscalationPolicyChannelsV1 = Field(..., alias="channels")
|
136
|
+
|
137
|
+
|
119
138
|
class GlitchtipProjectJiraV1(ConfiguredBaseModel):
|
120
139
|
project: Optional[str] = Field(..., alias="project")
|
121
|
-
|
140
|
+
components: Optional[list[str]] = Field(..., alias="components")
|
141
|
+
escalation_policy: Optional[AppEscalationPolicyV1] = Field(..., alias="escalationPolicy")
|
122
142
|
labels: Optional[list[str]] = Field(..., alias="labels")
|
123
143
|
|
124
144
|
|
125
|
-
class
|
145
|
+
class GlitchtipProjectV1(ConfiguredBaseModel):
|
126
146
|
name: str = Field(..., alias="name")
|
127
147
|
project_id: Optional[str] = Field(..., alias="projectId")
|
128
148
|
organization: GlitchtipOrganizationV1 = Field(..., alias="organization")
|
@@ -131,7 +151,7 @@ class GlitchtipProjectsV1(ConfiguredBaseModel):
|
|
131
151
|
|
132
152
|
|
133
153
|
class GlitchtipProjectsWithAlertsQueryData(ConfiguredBaseModel):
|
134
|
-
glitchtip_projects: Optional[list[
|
154
|
+
glitchtip_projects: Optional[list[GlitchtipProjectV1]] = Field(..., alias="glitchtip_projects")
|
135
155
|
|
136
156
|
|
137
157
|
def query(query_func: Callable, **kwargs: Any) -> GlitchtipProjectsWithAlertsQueryData:
|
@@ -6,10 +6,7 @@ from collections.abc import (
|
|
6
6
|
Mapping,
|
7
7
|
Sequence,
|
8
8
|
)
|
9
|
-
from typing import
|
10
|
-
Any,
|
11
|
-
Optional,
|
12
|
-
)
|
9
|
+
from typing import Any
|
13
10
|
|
14
11
|
from github import Github
|
15
12
|
from pydantic import BaseModel
|
@@ -76,7 +73,7 @@ def collect_parameters(
|
|
76
73
|
environment: EnvironmentV1,
|
77
74
|
upstream: str,
|
78
75
|
image: str,
|
79
|
-
image_tag_from_ref:
|
76
|
+
image_tag_from_ref: Mapping[str, str] | None,
|
80
77
|
) -> dict[str, Any]:
|
81
78
|
parameters: dict[str, Any] = {}
|
82
79
|
if environment.parameters:
|
@@ -180,7 +177,7 @@ def construct_oc_resources(
|
|
180
177
|
integrations_environment: IntegrationsEnvironment,
|
181
178
|
upstream: str,
|
182
179
|
image: str,
|
183
|
-
image_tag_from_ref:
|
180
|
+
image_tag_from_ref: Mapping[str, str] | None,
|
184
181
|
) -> list[OpenshiftResource]:
|
185
182
|
# Generate the openshift template with the helm chart. The resulting template
|
186
183
|
# contains all the integrations in the environment
|
@@ -213,7 +210,7 @@ def fetch_desired_state(
|
|
213
210
|
ri: ResourceInventory,
|
214
211
|
upstream: str,
|
215
212
|
image: str,
|
216
|
-
image_tag_from_ref:
|
213
|
+
image_tag_from_ref: Mapping[str, str] | None,
|
217
214
|
):
|
218
215
|
for ie in integrations_environments:
|
219
216
|
oc_resources = construct_oc_resources(ie, upstream, image, image_tag_from_ref)
|
@@ -224,7 +221,7 @@ def fetch_desired_state(
|
|
224
221
|
|
225
222
|
|
226
223
|
def filter_integrations(
|
227
|
-
integrations: Iterable[IntegrationV1], upstream:
|
224
|
+
integrations: Iterable[IntegrationV1], upstream: str | None = None
|
228
225
|
) -> list[IntegrationV1]:
|
229
226
|
if upstream is None:
|
230
227
|
return list(integrations)
|
reconcile/jenkins/types.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from enum import Enum
|
4
|
-
from typing import Optional
|
5
4
|
|
6
5
|
from pydantic import (
|
7
6
|
BaseModel,
|
@@ -22,11 +21,11 @@ class SSHHostKeyVerificationStrategy(Enum):
|
|
22
21
|
|
23
22
|
class SSHConnector(BaseModel):
|
24
23
|
credentials_id: str = Field(..., alias="credentialsId")
|
25
|
-
launch_timeout_seconds:
|
26
|
-
max_num_retries:
|
27
|
-
retry_wait_time:
|
28
|
-
port:
|
29
|
-
jvm_options:
|
24
|
+
launch_timeout_seconds: int | None = Field(None, alias="launchTimeoutSeconds")
|
25
|
+
max_num_retries: int | None = Field(None, alias="maxNumRetries")
|
26
|
+
retry_wait_time: int | None = Field(None, alias="retryWaitTime")
|
27
|
+
port: int | None = 22
|
28
|
+
jvm_options: str | None = Field(None, alias="jvmOptions")
|
30
29
|
ssh_host_key_verification_strategy: SSHHostKeyVerificationStrategy = Field(
|
31
30
|
SSHHostKeyVerificationStrategy.NON_VERIFYING_KEY_VERIFICATION_STRATEGY,
|
32
31
|
alias="sshHostKeyVerificationStrategy",
|
reconcile/jenkins_job_builder.py
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
3
|
from collections.abc import Callable
|
4
|
-
from typing import
|
5
|
-
Any,
|
6
|
-
Optional,
|
7
|
-
)
|
4
|
+
from typing import Any
|
8
5
|
|
9
6
|
from reconcile import queries
|
10
7
|
from reconcile.utils.defer import defer
|
@@ -20,7 +17,7 @@ GENERATE_TYPE = ["jobs", "views"]
|
|
20
17
|
|
21
18
|
|
22
19
|
def collect_configs(
|
23
|
-
instance_name:
|
20
|
+
instance_name: str | None, config_name: str | None
|
24
21
|
) -> list[dict[str, Any]]:
|
25
22
|
configs = queries.get_jenkins_configs()
|
26
23
|
if instance_name is not None:
|
@@ -41,8 +38,8 @@ def collect_configs(
|
|
41
38
|
|
42
39
|
def init_jjb(
|
43
40
|
secret_reader: SecretReaderBase,
|
44
|
-
instance_name:
|
45
|
-
config_name:
|
41
|
+
instance_name: str | None = None,
|
42
|
+
config_name: str | None = None,
|
46
43
|
print_only: bool = False,
|
47
44
|
) -> JJB:
|
48
45
|
configs = collect_configs(instance_name, config_name)
|
@@ -66,7 +63,7 @@ def validate_repos_and_admins(jjb: JJB):
|
|
66
63
|
)
|
67
64
|
unknown_admins = [a for a in jjb_admins if a not in github_usernames]
|
68
65
|
for a in unknown_admins:
|
69
|
-
logging.warning("admin is missing from users: {}"
|
66
|
+
logging.warning(f"admin is missing from users: {a}")
|
70
67
|
if missing_repos:
|
71
68
|
sys.exit(1)
|
72
69
|
|
@@ -76,10 +73,10 @@ def run(
|
|
76
73
|
dry_run: bool,
|
77
74
|
io_dir: str = "throughput/",
|
78
75
|
print_only: bool = False,
|
79
|
-
config_name:
|
80
|
-
job_name:
|
81
|
-
instance_name:
|
82
|
-
defer:
|
76
|
+
config_name: str | None = None,
|
77
|
+
job_name: str | None = None,
|
78
|
+
instance_name: str | None = None,
|
79
|
+
defer: Callable | None = None,
|
83
80
|
) -> None:
|
84
81
|
if not print_only and config_name is not None:
|
85
82
|
raise Exception("--config-name must works with --print-only mode")
|
reconcile/jenkins_roles.py
CHANGED
@@ -170,7 +170,7 @@ def act(diff, jenkins_map):
|
|
170
170
|
elif action == "unassign_role_from_user":
|
171
171
|
jenkins_map[instance].unassign_role_from_user(role, user)
|
172
172
|
else:
|
173
|
-
raise Exception("invalid action: {}"
|
173
|
+
raise Exception(f"invalid action: {action}")
|
174
174
|
|
175
175
|
|
176
176
|
def run(dry_run):
|