qontract-reconcile 0.9.1rc237__py3-none-any.whl → 0.9.1rc238__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.9.1rc237
3
+ Version: 0.9.1rc238
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
@@ -80,7 +80,7 @@ reconcile/openshift_namespaces.py,sha256=Pq2EE1OuClFYK66r6i-989B0h-K0IH5BKak7W-E
80
80
  reconcile/openshift_network_policies.py,sha256=X48jTvKOXhrLwWymkxbieYqJg01bDn90FnXFDr0WBI8,4189
81
81
  reconcile/openshift_resourcequotas.py,sha256=QR73mIa7rCEQgUqfRCCvlg9trqFNPjeIJZ_qVzY-mSQ,2795
82
82
  reconcile/openshift_resources.py,sha256=Lkn3KdIqxUCmOzlwoKjM2xVotTbJDfgjMGySvWtBZjU,1314
83
- reconcile/openshift_resources_base.py,sha256=RUUySaSdb3fY9isyMG1QnPNHZz9yVypB6C-xa-id8oc,40820
83
+ reconcile/openshift_resources_base.py,sha256=yyYBaZwtYbNW58ObLNyaAvC0xvy_Hhjo8iYdJTd5H3E,40365
84
84
  reconcile/openshift_rolebindings.py,sha256=1k0o3hb3ZhhlbUjc8cP7IjKFux0oZApT8kLT8Y-pvqI,6579
85
85
  reconcile/openshift_routes.py,sha256=fXvuPSjcjVw1X3j2EQvUAdbOepmIFdKk-M3qP8QzPiw,1075
86
86
  reconcile/openshift_saas_deploy.py,sha256=5ELZi8pKji6XIS55aRwusLRNat-RQoSbmw9H1cMN5PM,9949
@@ -324,8 +324,8 @@ reconcile/test/test_openshift_tekton_resources.py,sha256=Sn01SpAH1uYViuJXhzIvPPh
324
324
  reconcile/test/test_openshift_upgrade_watcher.py,sha256=o1Y5az-zp_ve0vAQNSu3NEPqUPLpQztEZI8WTka3opg,4784
325
325
  reconcile/test/test_prometheus_rules_tester.py,sha256=usJ_XgqiqoMDPj_2QAqKPeIsnuH99zs9dSbzV1PuzPk,1918
326
326
  reconcile/test/test_quay_membership.py,sha256=e29Giz5S9ckFgjpTO8PBo8qVPocIQmy4WqsRhgTFd9A,2643
327
- reconcile/test/test_quay_mirror.py,sha256=8Uu_4I_1uRQ35E1lXs-LPfYrk4BD3NdFdupjr4FxyJo,4142
328
- reconcile/test/test_quay_mirror_org.py,sha256=L01uGW1ICvSIB3kbU4l-moYkA5oE4X_PfszL_SBFz5Y,2589
327
+ reconcile/test/test_quay_mirror.py,sha256=Dc485iUwevbBue7TuE6eaz0WugwZD4v4IPTbd87SEHE,4142
328
+ reconcile/test/test_quay_mirror_org.py,sha256=93B6yrzUj7oWajsGl2pTXZ2OeEZn82t7hM106sj3H1o,2589
329
329
  reconcile/test/test_quay_repos.py,sha256=TdkcRF_a8PLp01Kti9eZZN-vGup2yPBT4Iba3k08qe0,1810
330
330
  reconcile/test/test_queries.py,sha256=SpH3RmNpBjEr_ne3VjAMCgKK8RE1z1zo7bypkT5uoO4,1946
331
331
  reconcile/test/test_repo_owners.py,sha256=uRYMLbMmh-9usF0TerabZTZV-Z1CS4I6ybT-LQqCLe8,1423
@@ -454,7 +454,7 @@ reconcile/utils/expiration.py,sha256=BXwKE50sNIV-Lszke97fxitNkLxYszoOLW1LBgp_yqg
454
454
  reconcile/utils/external_resource_spec.py,sha256=epSXhJU8PFmX0-YJWr4fre5mxbRDOyOS5vvYB-umMGA,6184
455
455
  reconcile/utils/external_resources.py,sha256=301hqVVDt78i88VLFTkSc5mq1KvVP4OiHh_DQX-B1G8,6492
456
456
  reconcile/utils/git.py,sha256=kgjN93MMB5mnkuNb1n53f5kldGGf5u0pBHj9YJbiE_c,1455
457
- reconcile/utils/git_secrets.py,sha256=Wot8ILeTyUhyxEDr15sr1KiRNZ3YsFlr3H8bJoYt7_4,2169
457
+ reconcile/utils/git_secrets.py,sha256=897nRs7tycA3m7YYeVEbzOhI8RFrI9IJT2E0di1eJhc,1956
458
458
  reconcile/utils/github_api.py,sha256=6gdlKK0W3vZpxbbtOcohRgvZ4YkiSki7Gxdb16goHPo,2316
459
459
  reconcile/utils/gitlab_api.py,sha256=_qRSdbzBxKzAhAeeBniH3AKd64R44M8ca4DHV9HBqFw,24610
460
460
  reconcile/utils/gpg.py,sha256=EKG7_fdMv8BMlV5yUdPiqoTx-KrzmVSEAl2sLkaKwWI,1123
@@ -470,10 +470,10 @@ reconcile/utils/jjb_client.py,sha256=L9rkfObDW6TsxcSJ1BMYkAL4zFXP_v_m4_sgrYULlj4
470
470
  reconcile/utils/jsonpath.py,sha256=8L3byngge3g6vNAYCXuHRRUsvUcFeC6hUAZPNmhh3bM,4675
471
471
  reconcile/utils/jump_host.py,sha256=yJZBRnoCJ-fknhT9f_cli_1J5hBRh1PsRVDyDWpjhws,4935
472
472
  reconcile/utils/ldap_client.py,sha256=atreTLA1f7gnG54Ub3JWkToP9tCwAci-q17dqB5XShA,1453
473
- reconcile/utils/lean_terraform_client.py,sha256=PJio087h5zUoievA3SppDP_io6ypiS9refaN5Hpm1Dg,1055
473
+ reconcile/utils/lean_terraform_client.py,sha256=no9MMgG6TsgjM3EypIhLQtRmPZl9eNnZ0k0llWSBn6Y,865
474
474
  reconcile/utils/make.py,sha256=QaEwucrzbl8-VHS66Wfdjfo0ubmAcvt_hZGpiGsKU50,231
475
475
  reconcile/utils/metrics.py,sha256=7DO12hEJ7sNOjrTNmA24l5wmAe4MT0WgY-Y2iPhBgXI,2015
476
- reconcile/utils/oc.py,sha256=_1ryGmPhSi5UNy8122l4sLDVU5xavy8ZpNpCSsOLDuk,68547
476
+ reconcile/utils/oc.py,sha256=-vPfw85S5Bgzy53OJqreP3UE2nL9fiAaiOWhzfxyPBs,68448
477
477
  reconcile/utils/oc_connection_parameters.py,sha256=jlEMObRAx0NuWQfEF7NXkLoY-Ewrr9egA7nUr_oUHyM,10011
478
478
  reconcile/utils/oc_filters.py,sha256=RWn8pC5A7ZZT7C6WPq9bOw5KBNkiAb5puFSr_FpdAf8,1358
479
479
  reconcile/utils/oc_map.py,sha256=2y8A2B7iSNG4dTxaF9OkKlbw0DYcUwjeF3uv-P0lTBM,9538
@@ -499,7 +499,7 @@ reconcile/utils/state.py,sha256=IMSrg2T11uP8xcxt6NIIuoWDhsun6qBYSWYFa8RmUZ0,7421
499
499
  reconcile/utils/structs.py,sha256=B05uQsZLxl4a-wLqiUTJ8ccr1dkjG_UbleMY2jrqoe0,296
500
500
  reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
501
501
  reconcile/utils/terraform_client.py,sha256=AYnA1pW7JgNuroHzhrLW8gZ8yN-pLKwH_aAnRj9JcEA,27679
502
- reconcile/utils/terrascript_aws_client.py,sha256=h5bCWv7MUk4b_dS3as4Aq9uyMcTxxDaT6tBj67tE0Hg,251172
502
+ reconcile/utils/terrascript_aws_client.py,sha256=4iAfp5DJ5Yeiuvh2phk42VE4cYeRzp-mw_5alVZpq3s,251109
503
503
  reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
504
504
  reconcile/utils/unleash.py,sha256=xY8fXxJApZhYnhJHmqNAK1YPNWf6larzDtk0VuNvn08,2875
505
505
  reconcile/utils/vault.py,sha256=CnhNu0pZfqS14kD1dQmBldITvTcSJHaHfk-KPNNDC7k,14471
@@ -561,8 +561,8 @@ tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y
561
561
  tools/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
562
562
  tools/test/test_qontract_cli.py,sha256=awwTHEc2DWlykuqGIYM0WOBoSL0KRnOraCLk3C7izis,1401
563
563
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
564
- qontract_reconcile-0.9.1rc237.dist-info/METADATA,sha256=zxJHMutcehp2XjsQeCt5IvLHBXOUIzhqjFqptYd7sFU,2248
565
- qontract_reconcile-0.9.1rc237.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
566
- qontract_reconcile-0.9.1rc237.dist-info/entry_points.txt,sha256=aIVvB7OTCxYu0QkONzBPfFEyg68Pr8KUVKEEm4ChDVc,333
567
- qontract_reconcile-0.9.1rc237.dist-info/top_level.txt,sha256=j0CHPIc8TsVRB50wOz_jhxjjaRyCJB3NOQeXhuHS67c,34
568
- qontract_reconcile-0.9.1rc237.dist-info/RECORD,,
564
+ qontract_reconcile-0.9.1rc238.dist-info/METADATA,sha256=47CGewECheJDS5LQ6I-pFcOYSP1LzRfeGMTDkFzO13M,2248
565
+ qontract_reconcile-0.9.1rc238.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
566
+ qontract_reconcile-0.9.1rc238.dist-info/entry_points.txt,sha256=aIVvB7OTCxYu0QkONzBPfFEyg68Pr8KUVKEEm4ChDVc,333
567
+ qontract_reconcile-0.9.1rc238.dist-info/top_level.txt,sha256=j0CHPIc8TsVRB50wOz_jhxjjaRyCJB3NOQeXhuHS67c,34
568
+ qontract_reconcile-0.9.1rc238.dist-info/RECORD,,
@@ -209,6 +209,21 @@ APP_INT_BASE_URL = "https://gitlab.cee.redhat.com/service/app-interface"
209
209
  _log_lock = Lock()
210
210
 
211
211
 
212
+ def _locked_info_log(msg: str):
213
+ with _log_lock:
214
+ logging.info(msg)
215
+
216
+
217
+ def _locked_debug_log(msg: str):
218
+ with _log_lock:
219
+ logging.debug(msg)
220
+
221
+
222
+ def _locked_error_log(msg: str):
223
+ with _log_lock:
224
+ logging.error(msg)
225
+
226
+
212
227
  class FetchSecretError(Exception):
213
228
  def __init__(self, msg):
214
229
  super().__init__("error fetching secret: " + str(msg))
@@ -538,8 +553,6 @@ def fetch_provider_vault_secret(
538
553
 
539
554
 
540
555
  def fetch_provider_route(resource: dict, tls_path, tls_version, settings=None) -> OR:
541
- global _log_lock
542
-
543
556
  path = resource["path"]
544
557
  openshift_resource = fetch_provider_resource(resource)
545
558
 
@@ -568,9 +581,7 @@ def fetch_provider_route(resource: dict, tls_path, tls_version, settings=None) -
568
581
  msg = "Route secret '{}' key '{}' not in valid keys {}".format(
569
582
  tls_path, k, valid_keys
570
583
  )
571
- _log_lock.acquire() # pylint: disable=consider-using-with
572
- logging.info(msg)
573
- _log_lock.release()
584
+ _locked_info_log(msg)
574
585
 
575
586
  host = openshift_resource.body["spec"].get("host")
576
587
  certificate = openshift_resource.body["spec"]["tls"].get("certificate")
@@ -583,21 +594,13 @@ def fetch_provider_route(resource: dict, tls_path, tls_version, settings=None) -
583
594
  return openshift_resource
584
595
 
585
596
 
586
- def _locked_log(lock, msg):
587
- lock.acquire() # pylint: disable=consider-using-with
588
- logging.debug(msg)
589
- lock.release()
590
-
591
-
592
597
  def fetch_openshift_resource(
593
598
  resource, parent, settings=None, skip_validation=False
594
599
  ) -> OR:
595
- global _log_lock
596
-
597
600
  provider = resource["provider"]
598
601
  if provider == "resource":
599
602
  path = resource["resource"]["path"]
600
- _locked_log(_log_lock, "Processing {}: {}".format(provider, path))
603
+ _locked_debug_log("Processing {}: {}".format(provider, path))
601
604
  validate_json = resource.get("validate_json") or False
602
605
  add_path_to_prom_rules = resource.get("add_path_to_prom_rules", True)
603
606
  validate_alertmanager_config = (
@@ -617,7 +620,7 @@ def fetch_openshift_resource(
617
620
  )
618
621
  elif provider == "resource-template":
619
622
  path = resource["resource"]["path"]
620
- _locked_log(_log_lock, "Processing {}: {}".format(provider, path))
623
+ _locked_debug_log("Processing {}: {}".format(provider, path))
621
624
  add_path_to_prom_rules = resource.get("add_path_to_prom_rules", True)
622
625
  validate_alertmanager_config = (
623
626
  resource.get("validate_alertmanager_config") or False
@@ -655,7 +658,7 @@ def fetch_openshift_resource(
655
658
  elif provider == "vault-secret":
656
659
  path = resource["path"]
657
660
  version = resource["version"]
658
- _locked_log(_log_lock, "Processing {}: {} - {}".format(provider, path, version))
661
+ _locked_debug_log("Processing {}: {} - {}".format(provider, path, version))
659
662
  rn = resource["name"]
660
663
  name = path.split("/")[-1] if rn is None else rn
661
664
  rl = resource["labels"]
@@ -688,7 +691,7 @@ def fetch_openshift_resource(
688
691
  raise FetchSecretError(e)
689
692
  elif provider == "route":
690
693
  path = resource["resource"]["path"]
691
- _locked_log(_log_lock, "Processing {}: {}".format(provider, path))
694
+ _locked_debug_log("Processing {}: {}".format(provider, path))
692
695
  tls_path = resource["vault_tls_secret_path"]
693
696
  tls_version = resource["vault_tls_secret_version"]
694
697
  openshift_resource = fetch_provider_route(
@@ -708,12 +711,7 @@ def fetch_current_state(
708
711
  kind: str,
709
712
  resource_names=Iterable[str],
710
713
  ):
711
- global _log_lock
712
-
713
- msg = f"Fetching {kind} from {cluster}/{namespace}"
714
- _log_lock.acquire() # pylint: disable=consider-using-with
715
- logging.debug(msg)
716
- _log_lock.release()
714
+ _locked_debug_log(f"Fetching {kind} from {cluster}/{namespace}")
717
715
  if not oc.is_kind_supported(kind):
718
716
  logging.warning(f"[{cluster}] cluster has no API resource {kind}.")
719
717
  return
@@ -740,8 +738,6 @@ def fetch_desired_state(
740
738
  privileged: bool,
741
739
  settings: Optional[Mapping[str, Any]] = None,
742
740
  ):
743
- global _log_lock
744
-
745
741
  try:
746
742
  openshift_resource = fetch_openshift_resource(resource, parent, settings)
747
743
  except (
@@ -752,9 +748,7 @@ def fetch_desired_state(
752
748
  ) as e:
753
749
  ri.register_error()
754
750
  msg = "[{}/{}] {}".format(cluster, namespace, str(e))
755
- _log_lock.acquire() # pylint: disable=consider-using-with
756
- logging.error(msg)
757
- _log_lock.release()
751
+ _locked_error_log(msg)
758
752
  return
759
753
 
760
754
  # add to inventory
@@ -774,9 +768,7 @@ def fetch_desired_state(
774
768
  msg = "[{}/{}] unknown kind: {}. hint: is it missing from managedResourceTypes?".format(
775
769
  cluster, namespace, openshift_resource.kind
776
770
  )
777
- _log_lock.acquire() # pylint: disable=consider-using-with
778
- logging.error(msg)
779
- _log_lock.release()
771
+ _locked_error_log(msg)
780
772
  return
781
773
  except ResourceKeyExistsError:
782
774
  # This is failing because an attempt to add
@@ -786,9 +778,7 @@ def fetch_desired_state(
786
778
  msg = ("[{}/{}] desired item already exists: {}/{}.").format(
787
779
  cluster, namespace, openshift_resource.kind, openshift_resource.name
788
780
  )
789
- _log_lock.acquire() # pylint: disable=consider-using-with
790
- logging.error(msg)
791
- _log_lock.release()
781
+ _locked_error_log(msg)
792
782
  return
793
783
 
794
784
 
@@ -48,7 +48,7 @@ class TestIsCompareTags:
48
48
  with open(os.path.join(self.tmp_dir.name, CONTROL_FILE_NAME), "w") as fh:
49
49
  fh.write(str(NOW - 100.0))
50
50
 
51
- def teardown_mehtod(self):
51
+ def teardown_method(self):
52
52
  self.tmp_dir.cleanup()
53
53
 
54
54
  # Last run was in NOW - 100s, we run compare tags every 10s.
@@ -36,7 +36,7 @@ class TestIsCompareTags:
36
36
  with open(os.path.join(self.tmp_dir.name, CONTROL_FILE_NAME), "w") as fh:
37
37
  fh.write(str(NOW - 100.0))
38
38
 
39
- def teardown_mehtod(self):
39
+ def teardown_method(self):
40
40
  self.tmp_dir.cleanup()
41
41
 
42
42
  # Last run was in NOW - 100s, we run compare tags every 10s.
@@ -1,54 +1,38 @@
1
1
  import logging
2
2
  import os
3
- import shutil
3
+ import subprocess
4
4
  import tempfile
5
- from subprocess import (
6
- PIPE,
7
- Popen,
8
- )
9
5
 
10
6
  import requests
11
7
  from sretoolbox.utils import retry
12
8
 
13
9
  from reconcile.utils import git
14
- from reconcile.utils.defer import defer
15
10
 
16
11
 
17
- @defer
18
12
  @retry()
19
- def scan_history(repo_url, existing_keys, defer=None):
20
- # pylint: disable=consider-using-with
13
+ def scan_history(repo_url, existing_keys):
21
14
  logging.info("scanning {}".format(repo_url))
22
15
  if requests.get(repo_url, timeout=60).status_code == 404:
23
16
  logging.info("not found {}".format(repo_url))
24
17
  return []
25
18
 
26
- wd = tempfile.mkdtemp()
27
- defer(lambda: cleanup(wd))
28
-
29
- git.clone(repo_url, wd)
30
- DEVNULL = open(os.devnull, "w")
31
- proc = Popen(["git", "secrets", "--register-aws"], cwd=wd, stdout=DEVNULL)
32
- proc.communicate()
33
- proc = Popen(["git", "secrets", "--scan-history"], cwd=wd, stdout=PIPE, stderr=PIPE)
34
- _, err = proc.communicate()
35
- if proc.returncode == 0:
36
- return []
37
-
38
- logging.info("found suspects in {}".format(repo_url))
39
- suspected_files = get_suspected_files(err.decode("utf-8"))
40
- leaked_keys = get_leaked_keys(wd, suspected_files, existing_keys)
41
- if leaked_keys:
42
- logging.info("found suspected leaked keys: {}".format(leaked_keys))
43
-
44
- return leaked_keys
45
-
46
-
47
- def cleanup(wd):
48
- try:
49
- shutil.rmtree(wd)
50
- except Exception:
51
- pass
19
+ with tempfile.TemporaryDirectory() as wd:
20
+ git.clone(repo_url, wd)
21
+ subprocess.run(["git", "secrets", "--install"], check=False, cwd=wd)
22
+ result = subprocess.run(
23
+ ["git", "secrets", "--scan-history"],
24
+ capture_output=True,
25
+ check=False,
26
+ cwd=wd,
27
+ )
28
+ if result.returncode == 0:
29
+ return []
30
+ logging.info("found suspects in {}".format(repo_url))
31
+ suspected_files = get_suspected_files(result.stderr.decode("utf-8"))
32
+ leaked_keys = get_leaked_keys(wd, suspected_files, existing_keys)
33
+ if leaked_keys:
34
+ logging.info("found suspected leaked keys: {}".format(leaked_keys))
35
+ return leaked_keys
52
36
 
53
37
 
54
38
  def get_suspected_files(error):
@@ -1,38 +1,27 @@
1
1
  import json
2
2
  import logging
3
- from subprocess import (
4
- PIPE,
5
- Popen,
6
- )
3
+ import subprocess
7
4
 
8
5
 
9
6
  def state_rm_access_key(working_dirs, account, user):
10
- # pylint: disable=consider-using-with
11
7
  wd = working_dirs[account]
12
- proc = Popen(["terraform", "init"], cwd=wd, stdout=PIPE, stderr=PIPE)
13
- proc.communicate()
14
- if proc.returncode:
8
+ init_result = subprocess.run(["terraform", "init"], check=False, cwd=wd)
9
+ if init_result.returncode != 0:
15
10
  return False
16
11
  resource = "aws_iam_access_key.{}".format(user)
17
- proc = Popen(
18
- ["terraform", "state", "rm", resource], cwd=wd, stdout=PIPE, stderr=PIPE
19
- )
20
- proc.communicate()
21
- return proc.returncode == 0
12
+ result = subprocess.run(["terraform", "state", "rm", resource], check=False, cwd=wd)
13
+ return result.returncode == 0
22
14
 
23
15
 
24
16
  def show_json(working_dir, out_file):
25
- # pylint: disable=consider-using-with
26
- proc = Popen(
17
+ result = subprocess.run(
27
18
  ["terraform", "show", "-no-color", "-json", out_file],
19
+ capture_output=True,
20
+ check=False,
28
21
  cwd=working_dir,
29
- stdout=PIPE,
30
- stderr=PIPE,
31
22
  )
32
- out, err = proc.communicate()
33
- if proc.returncode:
34
- # out_file is the name of the account as well
35
- msg = f"[{out_file}] terraform show failed: {str(err)}"
23
+ if result.returncode != 0:
24
+ msg = f"[{out_file}] terraform show failed: {result.stderr.decode('utf-8')}"
36
25
  logging.warning(msg)
37
26
  raise Exception(msg)
38
- return json.loads(out)
27
+ return json.loads(result.stdout)
reconcile/utils/oc.py CHANGED
@@ -3,6 +3,7 @@ import json
3
3
  import logging
4
4
  import os
5
5
  import re
6
+ import subprocess
6
7
  import tempfile
7
8
  import threading
8
9
  import time
@@ -14,10 +15,7 @@ from contextlib import suppress
14
15
  from dataclasses import dataclass
15
16
  from datetime import datetime
16
17
  from functools import wraps
17
- from subprocess import (
18
- PIPE,
19
- Popen,
20
- )
18
+ from subprocess import Popen
21
19
  from threading import Lock
22
20
  from typing import (
23
21
  Any,
@@ -1070,24 +1068,14 @@ class OCDeprecated: # pylint: disable=too-many-public-methods
1070
1068
 
1071
1069
  @retry(exceptions=(StatusCodeError, NoOutputError), max_attempts=10)
1072
1070
  def _run(self, cmd, **kwargs):
1073
- if kwargs.get("stdin"):
1074
- stdin = PIPE
1075
- stdin_text = kwargs.get("stdin").encode()
1076
- else:
1077
- stdin = None
1078
- stdin_text = None
1079
-
1080
- p = Popen( # pylint: disable=consider-using-with
1081
- self.oc_base_cmd + cmd, stdin=stdin, stdout=PIPE, stderr=PIPE
1071
+ stdin = kwargs.get("stdin")
1072
+ stdin_text = stdin.encode() if stdin else None
1073
+ result = subprocess.run(
1074
+ self.oc_base_cmd + cmd, input=stdin_text, capture_output=True, check=False
1082
1075
  )
1083
- out, err = p.communicate(stdin_text)
1084
-
1085
- code = p.returncode
1086
-
1076
+ err = result.stderr.decode("utf-8") if result.stderr else ""
1087
1077
  allow_not_found = kwargs.get("allow_not_found")
1088
-
1089
- if code != 0:
1090
- err = err.decode("utf-8")
1078
+ if result.returncode != 0:
1091
1079
  if "Unable to connect to the server" in err:
1092
1080
  raise StatusCodeError(f"[{self.server}]: {err}")
1093
1081
  if kwargs.get("apply"):
@@ -1120,12 +1108,12 @@ class OCDeprecated: # pylint: disable=too-many-public-methods
1120
1108
  if not (allow_not_found and "NotFound" in err):
1121
1109
  raise StatusCodeError(f"[{self.server}]: {err}")
1122
1110
 
1123
- if not out:
1111
+ if not result.stdout:
1124
1112
  if allow_not_found:
1125
1113
  return "{}"
1126
1114
  raise NoOutputError(err)
1127
1115
 
1128
- return out.strip()
1116
+ return result.stdout.decode("utf-8").strip()
1129
1117
 
1130
1118
  def _run_json(self, cmd, allow_not_found=False):
1131
1119
  out = self._run(cmd, allow_not_found=allow_not_found)
@@ -488,8 +488,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
488
488
  r = requests.get(zip_url, timeout=60)
489
489
  r.raise_for_status()
490
490
  os.makedirs(os.path.dirname(zip_file), exist_ok=True)
491
- # pylint: disable=consider-using-with
492
- open(zip_file, "wb").write(r.content)
491
+ with open(zip_file, "wb") as f:
492
+ f.write(r.content)
493
493
  return zip_file
494
494
 
495
495
  def get_logtoes_zip(self, release_url):
@@ -513,8 +513,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
513
513
  if not os.path.exists(zip_file):
514
514
  r = requests.get(zip_url, timeout=60)
515
515
  r.raise_for_status()
516
- # pylint: disable=consider-using-with
517
- open(zip_file, "wb").write(r.content)
516
+ with open(zip_file, "wb") as f:
517
+ f.write(r.content)
518
518
  return zip_file
519
519
 
520
520
  def get_rosa_authenticator_zip(self, release_url):
@@ -542,8 +542,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
542
542
  if not os.path.exists(zip_file):
543
543
  r = requests.get(zip_url, timeout=60)
544
544
  r.raise_for_status()
545
- # pylint: disable=consider-using-with
546
- open(zip_file, "wb").write(r.content)
545
+ with open(zip_file, "wb") as f:
546
+ f.write(r.content)
547
547
  return zip_file
548
548
 
549
549
  def init_github(self) -> Github: