qontract-reconcile 0.9.1rc235__py3-none-any.whl → 0.9.1rc236__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.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/METADATA +1 -2
- {qontract_reconcile-0.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/RECORD +19 -20
- reconcile/gql_definitions/common/saas_files.py +37 -40
- reconcile/gql_definitions/saas_auto_promotions_manager/saas_files_for_auto_promotion.py +1 -1
- reconcile/openshift_saas_deploy.py +5 -3
- reconcile/openshift_saas_deploy_change_tester.py +2 -9
- reconcile/queries.py +282 -0
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +0 -3
- reconcile/test/test_saasherder.py +0 -118
- reconcile/test/test_saasherder_allowed_secret_paths.py +3 -3
- reconcile/test/test_typed_queries.py +35 -0
- reconcile/typed_queries/saas_files.py +5 -212
- reconcile/utils/saasherder/interfaces.py +1 -1
- reconcile/utils/saasherder/saasherder.py +0 -30
- tools/app_interface_reporter.py +1 -5
- tools/qontract_cli.py +28 -93
- reconcile/gql_definitions/common/saas_target_namespaces.py +0 -118
- reconcile/gql_definitions/fragments/saas_target_namespace.py +0 -53
- {qontract_reconcile-0.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/top_level.txt +0 -0
tools/qontract_cli.py
CHANGED
@@ -8,24 +8,15 @@ import sys
|
|
8
8
|
from collections import defaultdict
|
9
9
|
from datetime import datetime
|
10
10
|
from operator import itemgetter
|
11
|
-
from typing import
|
12
|
-
Any,
|
13
|
-
Optional,
|
14
|
-
)
|
11
|
+
from typing import Optional
|
15
12
|
|
16
13
|
import click
|
17
14
|
import requests
|
18
15
|
import yaml
|
19
|
-
from rich import box
|
20
|
-
from rich.console import (
|
21
|
-
Console,
|
22
|
-
Group,
|
23
|
-
)
|
24
|
-
from rich.table import Table
|
25
|
-
from rich.tree import Tree
|
26
16
|
from sretoolbox.utils import threaded
|
27
17
|
|
28
18
|
import reconcile.aus.base as aus
|
19
|
+
import reconcile.gitlab_housekeeping as glhk
|
29
20
|
import reconcile.openshift_base as ob
|
30
21
|
import reconcile.openshift_resources_base as orb
|
31
22
|
import reconcile.terraform_resources as tfr
|
@@ -53,7 +44,6 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
53
44
|
get_app_interface_vault_settings,
|
54
45
|
)
|
55
46
|
from reconcile.typed_queries.clusters import get_clusters
|
56
|
-
from reconcile.typed_queries.saas_files import get_saas_files
|
57
47
|
from reconcile.utils import (
|
58
48
|
amtool,
|
59
49
|
config,
|
@@ -86,7 +76,6 @@ from reconcile.utils.oc import (
|
|
86
76
|
from reconcile.utils.oc_map import init_oc_map_from_clusters
|
87
77
|
from reconcile.utils.ocm import OCMMap
|
88
78
|
from reconcile.utils.output import print_output
|
89
|
-
from reconcile.utils.saasherder.saasherder import SaasHerder
|
90
79
|
from reconcile.utils.secret_reader import (
|
91
80
|
SecretReader,
|
92
81
|
create_secret_reader,
|
@@ -1654,8 +1643,6 @@ def sre_checkpoints(ctx):
|
|
1654
1643
|
@get.command()
|
1655
1644
|
@click.pass_context
|
1656
1645
|
def app_interface_merge_queue(ctx):
|
1657
|
-
import reconcile.gitlab_housekeeping as glhk
|
1658
|
-
|
1659
1646
|
settings = queries.get_app_interface_settings()
|
1660
1647
|
instance = queries.get_gitlab_instance()
|
1661
1648
|
gl = GitLabApi(instance, project_url=settings["repoUrl"], settings=settings)
|
@@ -1695,8 +1682,6 @@ def app_interface_merge_queue(ctx):
|
|
1695
1682
|
@get.command()
|
1696
1683
|
@click.pass_context
|
1697
1684
|
def app_interface_review_queue(ctx) -> None:
|
1698
|
-
import reconcile.gitlab_housekeeping as glhk
|
1699
|
-
|
1700
1685
|
settings = queries.get_app_interface_settings()
|
1701
1686
|
instance = queries.get_gitlab_instance()
|
1702
1687
|
secret_reader = SecretReader(settings=settings)
|
@@ -2469,26 +2454,36 @@ def alert_to_receiver(
|
|
2469
2454
|
@click.option("--saas-file-name", default=None, help="saas-file to act on.")
|
2470
2455
|
@click.option("--env-name", default=None, help="environment to use for parameters.")
|
2471
2456
|
@click.pass_context
|
2472
|
-
def saas_dev(ctx, app_name=None, saas_file_name=None, env_name=None)
|
2457
|
+
def saas_dev(ctx, app_name=None, saas_file_name=None, env_name=None):
|
2473
2458
|
if env_name in [None, ""]:
|
2474
2459
|
print("env-name must be defined")
|
2475
2460
|
return
|
2476
|
-
saas_files = get_saas_files(saas_file_name, env_name, app_name)
|
2461
|
+
saas_files = queries.get_saas_files(saas_file_name, env_name, app_name)
|
2477
2462
|
if not saas_files:
|
2478
2463
|
print("no saas files found")
|
2479
2464
|
sys.exit(1)
|
2480
|
-
|
2481
2465
|
for saas_file in saas_files:
|
2482
|
-
|
2483
|
-
|
2484
|
-
|
2466
|
+
saas_file_parameters = json.loads(saas_file.get("parameters") or "{}")
|
2467
|
+
for rt in saas_file["resourceTemplates"]:
|
2468
|
+
url = rt["url"]
|
2469
|
+
path = rt["path"]
|
2470
|
+
rt_parameters = json.loads(rt.get("parameters") or "{}")
|
2471
|
+
for target in rt["targets"]:
|
2472
|
+
target_parameters = json.loads(target.get("parameters") or "{}")
|
2473
|
+
namespace = target["namespace"]
|
2474
|
+
namespace_name = namespace["name"]
|
2475
|
+
environment = namespace["environment"]
|
2476
|
+
if environment["name"] != env_name:
|
2485
2477
|
continue
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
parameters
|
2491
|
-
parameters.update(
|
2478
|
+
ref = target["ref"]
|
2479
|
+
environment_parameters = json.loads(
|
2480
|
+
environment.get("parameters") or "{}"
|
2481
|
+
)
|
2482
|
+
parameters = {}
|
2483
|
+
parameters.update(environment_parameters)
|
2484
|
+
parameters.update(saas_file_parameters)
|
2485
|
+
parameters.update(rt_parameters)
|
2486
|
+
parameters.update(target_parameters)
|
2492
2487
|
|
2493
2488
|
for replace_key, replace_value in parameters.items():
|
2494
2489
|
if not isinstance(replace_value, str):
|
@@ -2503,79 +2498,19 @@ def saas_dev(ctx, app_name=None, saas_file_name=None, env_name=None) -> None:
|
|
2503
2498
|
parameters_cmd = ""
|
2504
2499
|
for k, v in parameters.items():
|
2505
2500
|
parameters_cmd += f' -p {k}="{v}"'
|
2506
|
-
raw_url =
|
2501
|
+
raw_url = url.replace("github.com", "raw.githubusercontent.com")
|
2507
2502
|
if "gitlab" in raw_url:
|
2508
2503
|
raw_url += "/raw"
|
2509
|
-
raw_url += "/" +
|
2510
|
-
raw_url +=
|
2504
|
+
raw_url += "/" + ref
|
2505
|
+
raw_url += path
|
2511
2506
|
cmd = (
|
2512
2507
|
"oc process --local --ignore-unknown-parameters"
|
2513
2508
|
+ f"{parameters_cmd} -f {raw_url}"
|
2514
|
-
+ f" | oc apply -n {
|
2509
|
+
+ f" | oc apply -n {namespace_name} -f - --dry-run"
|
2515
2510
|
)
|
2516
2511
|
print(cmd)
|
2517
2512
|
|
2518
2513
|
|
2519
|
-
@root.command()
|
2520
|
-
@click.option("--saas-file-name", default=None, help="saas-file to act on.")
|
2521
|
-
@click.option("--app-name", default=None, help="app to act on.")
|
2522
|
-
@click.pass_context
|
2523
|
-
def saas_targets(
|
2524
|
-
ctx, saas_file_name: Optional[str] = None, app_name: Optional[str] = None
|
2525
|
-
) -> None:
|
2526
|
-
"""Resolve namespaceSelectors and print all resulting targets of a saas file."""
|
2527
|
-
console = Console()
|
2528
|
-
if not saas_file_name and not app_name:
|
2529
|
-
console.print("[b red]saas-file-name or app-name must be given")
|
2530
|
-
sys.exit(1)
|
2531
|
-
|
2532
|
-
saas_files = get_saas_files(name=saas_file_name, app_name=app_name)
|
2533
|
-
if not saas_files:
|
2534
|
-
console.print("[b red]no saas files found")
|
2535
|
-
sys.exit(1)
|
2536
|
-
|
2537
|
-
SaasHerder.resolve_templated_parameters(saas_files)
|
2538
|
-
root = Tree("Saas Files", highlight=True, hide_root=True)
|
2539
|
-
for saas_file in saas_files:
|
2540
|
-
saas_file_node = root.add(f":notebook: Saas File: [b green]{saas_file.name}")
|
2541
|
-
for rt in saas_file.resource_templates:
|
2542
|
-
rt_node = saas_file_node.add(
|
2543
|
-
f":page_with_curl: Resource Template: [b blue]{rt.name}"
|
2544
|
-
)
|
2545
|
-
for target in rt.targets:
|
2546
|
-
info = Table("Key", "Value")
|
2547
|
-
info.add_row("Ref", target.ref)
|
2548
|
-
info.add_row(
|
2549
|
-
"Cluster/Namespace",
|
2550
|
-
f"{target.namespace.cluster.name}/{target.namespace.name}",
|
2551
|
-
)
|
2552
|
-
|
2553
|
-
if target.parameters:
|
2554
|
-
param_table = Table("Key", "Value", box=box.MINIMAL)
|
2555
|
-
for k, v in target.parameters.items():
|
2556
|
-
param_table.add_row(k, v)
|
2557
|
-
info.add_row("Parameters", param_table)
|
2558
|
-
|
2559
|
-
if target.secret_parameters:
|
2560
|
-
param_table = Table(
|
2561
|
-
"Name", "Path", "Field", "Version", box=box.MINIMAL
|
2562
|
-
)
|
2563
|
-
for secret in target.secret_parameters:
|
2564
|
-
param_table.add_row(
|
2565
|
-
secret.name,
|
2566
|
-
secret.secret.path,
|
2567
|
-
secret.secret.field,
|
2568
|
-
str(secret.secret.version),
|
2569
|
-
)
|
2570
|
-
info.add_row("Secret Parameters", param_table)
|
2571
|
-
|
2572
|
-
rt_node.add(
|
2573
|
-
Group(f"🎯 Target: [b yellow]{target.name or 'No name'}", info)
|
2574
|
-
)
|
2575
|
-
|
2576
|
-
console.print(root)
|
2577
|
-
|
2578
|
-
|
2579
2514
|
@root.command()
|
2580
2515
|
@click.argument("query")
|
2581
2516
|
@click.option(
|
@@ -1,118 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
|
3
|
-
"""
|
4
|
-
from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
|
5
|
-
from datetime import datetime # noqa: F401 # pylint: disable=W0611
|
6
|
-
from enum import Enum # noqa: F401 # pylint: disable=W0611
|
7
|
-
from typing import ( # noqa: F401 # pylint: disable=W0611
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
Union,
|
11
|
-
)
|
12
|
-
|
13
|
-
from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
14
|
-
BaseModel,
|
15
|
-
Extra,
|
16
|
-
Field,
|
17
|
-
Json,
|
18
|
-
)
|
19
|
-
|
20
|
-
from reconcile.gql_definitions.fragments.saas_target_namespace import (
|
21
|
-
SaasTargetNamespace,
|
22
|
-
)
|
23
|
-
|
24
|
-
|
25
|
-
DEFINITION = """
|
26
|
-
fragment CommonJumphostFields on ClusterJumpHost_v1 {
|
27
|
-
hostname
|
28
|
-
knownHosts
|
29
|
-
user
|
30
|
-
port
|
31
|
-
remotePort
|
32
|
-
identity {
|
33
|
-
... VaultSecret
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
fragment OcConnectionCluster on Cluster_v1 {
|
38
|
-
name
|
39
|
-
serverUrl
|
40
|
-
internal
|
41
|
-
insecureSkipTLSVerify
|
42
|
-
jumpHost {
|
43
|
-
...CommonJumphostFields
|
44
|
-
}
|
45
|
-
automationToken {
|
46
|
-
...VaultSecret
|
47
|
-
}
|
48
|
-
clusterAdminAutomationToken {
|
49
|
-
...VaultSecret
|
50
|
-
}
|
51
|
-
disable {
|
52
|
-
integrations
|
53
|
-
e2eTests
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
fragment SaasTargetNamespace on Namespace_v1 {
|
58
|
-
name
|
59
|
-
environment {
|
60
|
-
name
|
61
|
-
parameters
|
62
|
-
secretParameters {
|
63
|
-
name
|
64
|
-
secret {
|
65
|
-
...VaultSecret
|
66
|
-
}
|
67
|
-
}
|
68
|
-
}
|
69
|
-
app {
|
70
|
-
name
|
71
|
-
}
|
72
|
-
cluster {
|
73
|
-
...OcConnectionCluster
|
74
|
-
}
|
75
|
-
}
|
76
|
-
|
77
|
-
fragment VaultSecret on VaultSecret_v1 {
|
78
|
-
path
|
79
|
-
field
|
80
|
-
version
|
81
|
-
format
|
82
|
-
}
|
83
|
-
|
84
|
-
query SaasFileTargetNamespaces {
|
85
|
-
namespaces: namespaces_v1 {
|
86
|
-
...SaasTargetNamespace
|
87
|
-
}
|
88
|
-
}
|
89
|
-
"""
|
90
|
-
|
91
|
-
|
92
|
-
class ConfiguredBaseModel(BaseModel):
|
93
|
-
class Config:
|
94
|
-
smart_union = True
|
95
|
-
extra = Extra.forbid
|
96
|
-
|
97
|
-
|
98
|
-
class SaasFileTargetNamespacesQueryData(ConfiguredBaseModel):
|
99
|
-
namespaces: Optional[list[SaasTargetNamespace]] = Field(..., alias="namespaces")
|
100
|
-
|
101
|
-
|
102
|
-
def query(query_func: Callable, **kwargs: Any) -> SaasFileTargetNamespacesQueryData:
|
103
|
-
"""
|
104
|
-
This is a convenience function which queries and parses the data into
|
105
|
-
concrete types. It should be compatible with most GQL clients.
|
106
|
-
You do not have to use it to consume the generated data classes.
|
107
|
-
Alternatively, you can also mime and alternate the behavior
|
108
|
-
of this function in the caller.
|
109
|
-
|
110
|
-
Parameters:
|
111
|
-
query_func (Callable): Function which queries your GQL Server
|
112
|
-
kwargs: optional arguments that will be passed to the query function
|
113
|
-
|
114
|
-
Returns:
|
115
|
-
SaasFileTargetNamespacesQueryData: queried data parsed into generated classes
|
116
|
-
"""
|
117
|
-
raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs)
|
118
|
-
return SaasFileTargetNamespacesQueryData(**raw_data)
|
@@ -1,53 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
|
3
|
-
"""
|
4
|
-
from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
|
5
|
-
from datetime import datetime # noqa: F401 # pylint: disable=W0611
|
6
|
-
from enum import Enum # noqa: F401 # pylint: disable=W0611
|
7
|
-
from typing import ( # noqa: F401 # pylint: disable=W0611
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
Union,
|
11
|
-
)
|
12
|
-
|
13
|
-
from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
14
|
-
BaseModel,
|
15
|
-
Extra,
|
16
|
-
Field,
|
17
|
-
Json,
|
18
|
-
)
|
19
|
-
|
20
|
-
from reconcile.gql_definitions.fragments.oc_connection_cluster import (
|
21
|
-
OcConnectionCluster,
|
22
|
-
)
|
23
|
-
from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
|
24
|
-
|
25
|
-
|
26
|
-
class ConfiguredBaseModel(BaseModel):
|
27
|
-
class Config:
|
28
|
-
smart_union = True
|
29
|
-
extra = Extra.forbid
|
30
|
-
|
31
|
-
|
32
|
-
class SaasSecretParametersV1(ConfiguredBaseModel):
|
33
|
-
name: str = Field(..., alias="name")
|
34
|
-
secret: VaultSecret = Field(..., alias="secret")
|
35
|
-
|
36
|
-
|
37
|
-
class EnvironmentV1(ConfiguredBaseModel):
|
38
|
-
name: str = Field(..., alias="name")
|
39
|
-
parameters: Optional[Json] = Field(..., alias="parameters")
|
40
|
-
secret_parameters: Optional[list[SaasSecretParametersV1]] = Field(
|
41
|
-
..., alias="secretParameters"
|
42
|
-
)
|
43
|
-
|
44
|
-
|
45
|
-
class AppV1(ConfiguredBaseModel):
|
46
|
-
name: str = Field(..., alias="name")
|
47
|
-
|
48
|
-
|
49
|
-
class SaasTargetNamespace(ConfiguredBaseModel):
|
50
|
-
name: str = Field(..., alias="name")
|
51
|
-
environment: EnvironmentV1 = Field(..., alias="environment")
|
52
|
-
app: AppV1 = Field(..., alias="app")
|
53
|
-
cluster: OcConnectionCluster = Field(..., alias="cluster")
|
File without changes
|
{qontract_reconcile-0.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/entry_points.txt
RENAMED
File without changes
|
{qontract_reconcile-0.9.1rc235.dist-info → qontract_reconcile-0.9.1rc236.dist-info}/top_level.txt
RENAMED
File without changes
|