qontract-reconcile 0.10.2.dev295__py3-none-any.whl → 0.10.2.dev297__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.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev295
3
+ Version: 0.10.2.dev297
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
6
6
  Project-URL: repository, https://github.com/app-sre/qontract-reconcile
@@ -82,12 +82,12 @@ reconcile/openshift_tekton_resources.py,sha256=z9OidaI7Ju2O0O0PfIcdoyH62VA4TxLTD
82
82
  reconcile/openshift_upgrade_watcher.py,sha256=dGTQQdCOl95Bz0wOqg6JaMdBSSDgnAveH_hprUafhW0,6624
83
83
  reconcile/openshift_users.py,sha256=h4dH3gTCFFQID76PFuYeMWNzFQ9DgTUtsOcvxfj-3cs,5385
84
84
  reconcile/openshift_vault_secrets.py,sha256=Ax-_EBWWU1VRHYyKaUkGJkIjHGwWM3bZgjXL5CkPW8k,1883
85
- reconcile/quay_base.py,sha256=GQkUpuEzC1V_QrHEu_PoELVGnlNRvgFnTqVKp-xkgC4,2070
85
+ reconcile/quay_base.py,sha256=hfHv8ET6iw0GqPyncYJMRH7YFwJc5E1C9z7zET5MCjo,2327
86
86
  reconcile/quay_membership.py,sha256=No2sgEyTVj-hr5VPLy_xdrYAPvt-xo-CPpOt0X3x_6o,6623
87
87
  reconcile/quay_mirror.py,sha256=pA1_OujRduwQ6dYljoWXU_VJgAwlv7DzThk26ymKmGs,14327
88
- reconcile/quay_mirror_org.py,sha256=2xLD-PZggP33LhZYxun5I3deF8hwGH9zueMtAByphzE,10842
88
+ reconcile/quay_mirror_org.py,sha256=ltPbHuWUI8Wnl8gV4aeYmvoYFA1uXLWqlXqEPpw7Hi0,11065
89
89
  reconcile/quay_permissions.py,sha256=BF539lRxjpgwm88WzazklzgaCF_ipRALwbO2AdpqUqE,4388
90
- reconcile/quay_repos.py,sha256=woB2afCBgz0UPekHcYtV8zwQCZHZZBL8VDf82ATWZxE,7524
90
+ reconcile/quay_repos.py,sha256=fBleLzMtfDmTidpzbrTt8kGCy-Bk3J06EO4hhyghGnQ,7570
91
91
  reconcile/queries.py,sha256=FLUZBtFC2S-e6yjtC1Oq968CJP6t3nc36NPj0wYa0bE,53472
92
92
  reconcile/query_validator.py,sha256=csOSkKxcf6ZlpchJu4ck2jLYKUN6y1l-UmSQUFHgssY,1618
93
93
  reconcile/requests_sender.py,sha256=914iluuF4UVgG3VyxxtnHOu4yf6YKS2fIy6PViSsFTQ,3875
@@ -135,7 +135,7 @@ reconcile/aus/version_gates/ocp_gate_handler.py,sha256=RW1ppDaCZXVegV9AzzqYXxDUu
135
135
  reconcile/aus/version_gates/sts_version_gate_handler.py,sha256=QDk53hXAEr6o8w3nGeVCrcihNohrMJztq4ZlsHq_35o,3655
136
136
  reconcile/automated_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
137
  reconcile/automated_actions/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
- reconcile/automated_actions/config/integration.py,sha256=EbVJGyEAFf91dHiIlnwbetbqZ3Y7HJOez2Fnexzd550,13853
138
+ reconcile/automated_actions/config/integration.py,sha256=5bnYJm9pdlZ_AD_F8oGQuWqyGVIDMsFmA6INKTzXRuQ,14638
139
139
  reconcile/aws_account_manager/README.md,sha256=_XFM3GZNHUzv--e_navqJuaUWpjC6QrHfulreHynFf0,262
140
140
  reconcile/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
141
  reconcile/aws_account_manager/integration.py,sha256=WEbcvF8GocFHJrlz3mmXSOyYHIUrrHxq_SKaImgJQ2c,15346
@@ -213,7 +213,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=d3PMy-mQSbSZdIGAVaZCA2U
213
213
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
214
214
  reconcile/glitchtip_project_dsn/integration.py,sha256=3GgcqUM6hWhLpo9Yx5Xr9vrdexF-WNevVCNL9bJ0Upc,8162
215
215
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
- reconcile/gql_definitions/introspection.json,sha256=CQAoUjEbdjRlHyYeLjs1PTMiP_RQrPzD0yCj08aYawA,2348381
216
+ reconcile/gql_definitions/introspection.json,sha256=Aak1w7K7K1fhgZoZNN2gQ2TV3Jwh0X2GhqfpqRLwWp4,2359202
217
217
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
218
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
219
219
  reconcile/gql_definitions/acs/acs_policies.py,sha256=Ygpfl2-VkYLSlJvHgp_dJBfb66K_Rwfdfpsa18w1v1s,4338
@@ -227,7 +227,7 @@ reconcile/gql_definitions/app_sre_tekton_access_revalidation/__init__.py,sha256=
227
227
  reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py,sha256=8Y4NsS5T7tumDWxY5MuoV50MK2i-DsLYSpCRjb7KaLE,2353
228
228
  reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py,sha256=XdVxBxiyTR6Cy939EHNw__0k7iWrZWlhrgS5DakST0I,2504
229
229
  reconcile/gql_definitions/automated_actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
- reconcile/gql_definitions/automated_actions/instance.py,sha256=6UPBKXPSjBsTXGdRQMK1ZXuns5pMPgYBscO3LxU3Gow,12406
230
+ reconcile/gql_definitions/automated_actions/instance.py,sha256=BGdArzLhns8EKsR3ROGtQx1WcFvsv25We7rzveBExhg,14183
231
231
  reconcile/gql_definitions/aws_account_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
232
232
  reconcile/gql_definitions/aws_account_manager/aws_accounts.py,sha256=vF51KrY2gwX0J9vESiaRMPQqdAMEtz9f_tBq52bInp0,5148
233
233
  reconcile/gql_definitions/aws_ami_cleanup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -637,11 +637,11 @@ reconcile/utils/openssl.py,sha256=QVvhzhpChq_4Daf_5wE1qeZJr4thg3DDjJPn4bOPD4E,36
637
637
  reconcile/utils/output.py,sha256=wvsyf8NsFTaFHNkc8to75ta8f474Y4TMO4cHyAHEePk,2209
638
638
  reconcile/utils/pagerduty_api.py,sha256=6Ae-KjcmA6Bf328UhTdQ2VwYjh4uFIW1NdZW6PUgT-c,7607
639
639
  reconcile/utils/parse_dhms_duration.py,sha256=TONpLnec5gHeF7k815YNJpQyDjXhkxZIcv9s8ffbTSY,1840
640
- reconcile/utils/password_validator.py,sha256=XwuWg-8CPlcuG7dl_oQ1G1h2gSVSnfMym_VkuprpWVg,2183
640
+ reconcile/utils/password_validator.py,sha256=knR6jJGc-v44v-hhQFvpYrEubuFfCCc3Qly6n_GJm5I,2191
641
641
  reconcile/utils/prometheus.py,sha256=Ad0rwLbxRuuYjHwkwJloHEdK0bvy42h-p-HIT1DhDhs,3832
642
642
  reconcile/utils/promotion_state.py,sha256=McSgGj3oog83ThJCrMR2v8q6Xb_Pxij-HEe_RbDu8cg,3946
643
643
  reconcile/utils/promtool.py,sha256=YnqwMAzsQVGuBZ1j9zy3UcVPFQVJgBMLzQkxhK_KFkU,3079
644
- reconcile/utils/quay_api.py,sha256=Z6e3oPSp8sCIYxUSDTc6r_qZmXN8Ci_gK90DSCF7BDw,7814
644
+ reconcile/utils/quay_api.py,sha256=ZWjfjzFnIsbKRDcdAnP9tWQezclf53I7VWZJ0gbF2kE,8260
645
645
  reconcile/utils/quay_mirror.py,sha256=dpWCNv5lITwIk6Q9RkmqaQKHNk_JPy27UQEribJ7E-U,1324
646
646
  reconcile/utils/raw_github_api.py,sha256=2WKtE8ABYYB9UGOAh9N_kLkksBWL3320Z2_scteZddI,2805
647
647
  reconcile/utils/repo_owners.py,sha256=P0QX6F0oB8wYA08yiyzhYUiBtU57iIK_PsxbzKENbKM,6571
@@ -796,7 +796,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
796
796
  tools/saas_promotion_state/saas_promotion_state.py,sha256=uQv2QJAmUXP1g2GPIH30WTlvL9soY6m9lefpZEVDM5w,3965
797
797
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
798
798
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
799
- qontract_reconcile-0.10.2.dev295.dist-info/METADATA,sha256=b48r1FF0GwIfFEiB6y-etqnHajQ5GHIn079H9KABEys,24916
800
- qontract_reconcile-0.10.2.dev295.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
801
- qontract_reconcile-0.10.2.dev295.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
802
- qontract_reconcile-0.10.2.dev295.dist-info/RECORD,,
799
+ qontract_reconcile-0.10.2.dev297.dist-info/METADATA,sha256=iGF5qMFr_OjJTe4VrXqoImqpXd6uvpYs0wXPJhdp1q0,24916
800
+ qontract_reconcile-0.10.2.dev297.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
801
+ qontract_reconcile-0.10.2.dev297.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
802
+ qontract_reconcile-0.10.2.dev297.dist-info/RECORD,,
@@ -20,6 +20,7 @@ from reconcile.gql_definitions.automated_actions.instance import (
20
20
  AutomatedActionExternalResourceFlushElastiCacheV1,
21
21
  AutomatedActionExternalResourceRdsRebootV1,
22
22
  AutomatedActionExternalResourceRdsSnapshotV1,
23
+ AutomatedActionOpenshiftWorkloadDeleteV1,
23
24
  AutomatedActionOpenshiftWorkloadRestartArgumentV1,
24
25
  AutomatedActionOpenshiftWorkloadRestartV1,
25
26
  AutomatedActionsInstanceV1,
@@ -204,6 +205,19 @@ class AutomatedActionsConfigIntegration(
204
205
  "account": f"^{rds_snapshot_er.provisioner.name}$",
205
206
  "identifier": rds_snapshot_arg.identifier,
206
207
  })
208
+ case AutomatedActionOpenshiftWorkloadDeleteV1():
209
+ parameters.extend(
210
+ {
211
+ # all parameter values are regexes in the OPA policy
212
+ # therefore, cluster and namespace must be fixed to the current strings
213
+ "cluster": f"^{arg.namespace.cluster.name}$",
214
+ "namespace": f"^{arg.namespace.name}$",
215
+ "api_version": arg.api_version or ".*",
216
+ "kind": arg.kind,
217
+ "name": arg.name,
218
+ }
219
+ for arg in action.openshift_workload_delete_arguments
220
+ )
207
221
  case AutomatedActionOpenshiftWorkloadRestartV1():
208
222
  parameters.extend(
209
223
  {
@@ -132,6 +132,23 @@ query AutomatedActionsInstances {
132
132
  identifier
133
133
  }
134
134
  }
135
+ ... on AutomatedActionOpenshiftWorkloadDelete_v1 {
136
+ openshift_workload_delete_arguments: arguments {
137
+ namespace {
138
+ name
139
+ delete
140
+ cluster {
141
+ name
142
+ disable {
143
+ integrations
144
+ }
145
+ }
146
+ }
147
+ api_version
148
+ kind
149
+ name
150
+ }
151
+ }
135
152
  ... on AutomatedActionOpenshiftWorkloadRestart_v1 {
136
153
  openshift_workload_restart_arguments: arguments {
137
154
  namespace {
@@ -280,11 +297,37 @@ class DisableClusterAutomationsV1(ConfiguredBaseModel):
280
297
  integrations: Optional[list[str]] = Field(..., alias="integrations")
281
298
 
282
299
 
283
- class AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1_ClusterV1(ConfiguredBaseModel):
300
+ class AutomatedActionOpenshiftWorkloadDeleteArgumentV1_NamespaceV1_ClusterV1(ConfiguredBaseModel):
284
301
  name: str = Field(..., alias="name")
285
302
  disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
286
303
 
287
304
 
305
+ class AutomatedActionOpenshiftWorkloadDeleteArgumentV1_NamespaceV1(ConfiguredBaseModel):
306
+ name: str = Field(..., alias="name")
307
+ delete: Optional[bool] = Field(..., alias="delete")
308
+ cluster: AutomatedActionOpenshiftWorkloadDeleteArgumentV1_NamespaceV1_ClusterV1 = Field(..., alias="cluster")
309
+
310
+
311
+ class AutomatedActionOpenshiftWorkloadDeleteArgumentV1(ConfiguredBaseModel):
312
+ namespace: AutomatedActionOpenshiftWorkloadDeleteArgumentV1_NamespaceV1 = Field(..., alias="namespace")
313
+ api_version: Optional[str] = Field(..., alias="api_version")
314
+ kind: str = Field(..., alias="kind")
315
+ name: str = Field(..., alias="name")
316
+
317
+
318
+ class AutomatedActionOpenshiftWorkloadDeleteV1(AutomatedActionV1):
319
+ openshift_workload_delete_arguments: list[AutomatedActionOpenshiftWorkloadDeleteArgumentV1] = Field(..., alias="openshift_workload_delete_arguments")
320
+
321
+
322
+ class AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1_ClusterV1_DisableClusterAutomationsV1(ConfiguredBaseModel):
323
+ integrations: Optional[list[str]] = Field(..., alias="integrations")
324
+
325
+
326
+ class AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1_ClusterV1(ConfiguredBaseModel):
327
+ name: str = Field(..., alias="name")
328
+ disable: Optional[AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1_ClusterV1_DisableClusterAutomationsV1] = Field(..., alias="disable")
329
+
330
+
288
331
  class AutomatedActionOpenshiftWorkloadRestartArgumentV1_NamespaceV1(ConfiguredBaseModel):
289
332
  name: str = Field(..., alias="name")
290
333
  delete: Optional[bool] = Field(..., alias="delete")
@@ -304,7 +347,7 @@ class AutomatedActionOpenshiftWorkloadRestartV1(AutomatedActionV1):
304
347
  class AutomatedActionsInstanceV1(ConfiguredBaseModel):
305
348
  name: str = Field(..., alias="name")
306
349
  deployment: NamespaceV1 = Field(..., alias="deployment")
307
- actions: Optional[list[Union[AutomatedActionActionListV1, AutomatedActionExternalResourceFlushElastiCacheV1, AutomatedActionExternalResourceRdsRebootV1, AutomatedActionExternalResourceRdsSnapshotV1, AutomatedActionOpenshiftWorkloadRestartV1, AutomatedActionV1]]] = Field(..., alias="actions")
350
+ actions: Optional[list[Union[AutomatedActionActionListV1, AutomatedActionExternalResourceFlushElastiCacheV1, AutomatedActionExternalResourceRdsRebootV1, AutomatedActionExternalResourceRdsSnapshotV1, AutomatedActionOpenshiftWorkloadDeleteV1, AutomatedActionOpenshiftWorkloadRestartV1, AutomatedActionV1]]] = Field(..., alias="actions")
308
351
 
309
352
 
310
353
  class AutomatedActionsInstancesQueryData(ConfiguredBaseModel):
@@ -5706,6 +5706,11 @@
5706
5706
  "name": "AutomatedActionNoOp_v1",
5707
5707
  "ofType": null
5708
5708
  },
5709
+ {
5710
+ "kind": "OBJECT",
5711
+ "name": "AutomatedActionOpenshiftWorkloadDelete_v1",
5712
+ "ofType": null
5713
+ },
5709
5714
  {
5710
5715
  "kind": "OBJECT",
5711
5716
  "name": "AutomatedActionOpenshiftWorkloadRestart_v1",
@@ -27325,6 +27330,11 @@
27325
27330
  "name": "AutomatedActionNoOp_v1",
27326
27331
  "ofType": null
27327
27332
  },
27333
+ {
27334
+ "kind": "OBJECT",
27335
+ "name": "AutomatedActionOpenshiftWorkloadDelete_v1",
27336
+ "ofType": null
27337
+ },
27328
27338
  {
27329
27339
  "kind": "OBJECT",
27330
27340
  "name": "AutomatedActionOpenshiftWorkloadRestart_v1",
@@ -53916,6 +53926,243 @@
53916
53926
  "enumValues": null,
53917
53927
  "possibleTypes": null
53918
53928
  },
53929
+ {
53930
+ "kind": "OBJECT",
53931
+ "name": "AutomatedActionOpenshiftWorkloadDelete_v1",
53932
+ "description": null,
53933
+ "fields": [
53934
+ {
53935
+ "name": "schema",
53936
+ "description": null,
53937
+ "args": [],
53938
+ "type": {
53939
+ "kind": "NON_NULL",
53940
+ "name": null,
53941
+ "ofType": {
53942
+ "kind": "SCALAR",
53943
+ "name": "String",
53944
+ "ofType": null
53945
+ }
53946
+ },
53947
+ "isDeprecated": false,
53948
+ "deprecationReason": null
53949
+ },
53950
+ {
53951
+ "name": "path",
53952
+ "description": null,
53953
+ "args": [],
53954
+ "type": {
53955
+ "kind": "NON_NULL",
53956
+ "name": null,
53957
+ "ofType": {
53958
+ "kind": "SCALAR",
53959
+ "name": "String",
53960
+ "ofType": null
53961
+ }
53962
+ },
53963
+ "isDeprecated": false,
53964
+ "deprecationReason": null
53965
+ },
53966
+ {
53967
+ "name": "type",
53968
+ "description": null,
53969
+ "args": [],
53970
+ "type": {
53971
+ "kind": "NON_NULL",
53972
+ "name": null,
53973
+ "ofType": {
53974
+ "kind": "SCALAR",
53975
+ "name": "String",
53976
+ "ofType": null
53977
+ }
53978
+ },
53979
+ "isDeprecated": false,
53980
+ "deprecationReason": null
53981
+ },
53982
+ {
53983
+ "name": "description",
53984
+ "description": null,
53985
+ "args": [],
53986
+ "type": {
53987
+ "kind": "SCALAR",
53988
+ "name": "String",
53989
+ "ofType": null
53990
+ },
53991
+ "isDeprecated": false,
53992
+ "deprecationReason": null
53993
+ },
53994
+ {
53995
+ "name": "maxOps",
53996
+ "description": null,
53997
+ "args": [],
53998
+ "type": {
53999
+ "kind": "NON_NULL",
54000
+ "name": null,
54001
+ "ofType": {
54002
+ "kind": "SCALAR",
54003
+ "name": "Int",
54004
+ "ofType": null
54005
+ }
54006
+ },
54007
+ "isDeprecated": false,
54008
+ "deprecationReason": null
54009
+ },
54010
+ {
54011
+ "name": "instances",
54012
+ "description": null,
54013
+ "args": [],
54014
+ "type": {
54015
+ "kind": "NON_NULL",
54016
+ "name": null,
54017
+ "ofType": {
54018
+ "kind": "LIST",
54019
+ "name": null,
54020
+ "ofType": {
54021
+ "kind": "NON_NULL",
54022
+ "name": null,
54023
+ "ofType": {
54024
+ "kind": "OBJECT",
54025
+ "name": "AutomatedActionsInstance_v1",
54026
+ "ofType": null
54027
+ }
54028
+ }
54029
+ }
54030
+ },
54031
+ "isDeprecated": false,
54032
+ "deprecationReason": null
54033
+ },
54034
+ {
54035
+ "name": "permissions",
54036
+ "description": null,
54037
+ "args": [],
54038
+ "type": {
54039
+ "kind": "LIST",
54040
+ "name": null,
54041
+ "ofType": {
54042
+ "kind": "NON_NULL",
54043
+ "name": null,
54044
+ "ofType": {
54045
+ "kind": "OBJECT",
54046
+ "name": "PermissionAutomatedActions_v1",
54047
+ "ofType": null
54048
+ }
54049
+ }
54050
+ },
54051
+ "isDeprecated": false,
54052
+ "deprecationReason": null
54053
+ },
54054
+ {
54055
+ "name": "arguments",
54056
+ "description": null,
54057
+ "args": [],
54058
+ "type": {
54059
+ "kind": "NON_NULL",
54060
+ "name": null,
54061
+ "ofType": {
54062
+ "kind": "LIST",
54063
+ "name": null,
54064
+ "ofType": {
54065
+ "kind": "NON_NULL",
54066
+ "name": null,
54067
+ "ofType": {
54068
+ "kind": "OBJECT",
54069
+ "name": "AutomatedActionOpenshiftWorkloadDeleteArgument_v1",
54070
+ "ofType": null
54071
+ }
54072
+ }
54073
+ }
54074
+ },
54075
+ "isDeprecated": false,
54076
+ "deprecationReason": null
54077
+ }
54078
+ ],
54079
+ "inputFields": null,
54080
+ "interfaces": [
54081
+ {
54082
+ "kind": "INTERFACE",
54083
+ "name": "AutomatedAction_v1",
54084
+ "ofType": null
54085
+ },
54086
+ {
54087
+ "kind": "INTERFACE",
54088
+ "name": "DatafileObject_v1",
54089
+ "ofType": null
54090
+ }
54091
+ ],
54092
+ "enumValues": null,
54093
+ "possibleTypes": null
54094
+ },
54095
+ {
54096
+ "kind": "OBJECT",
54097
+ "name": "AutomatedActionOpenshiftWorkloadDeleteArgument_v1",
54098
+ "description": null,
54099
+ "fields": [
54100
+ {
54101
+ "name": "namespace",
54102
+ "description": null,
54103
+ "args": [],
54104
+ "type": {
54105
+ "kind": "NON_NULL",
54106
+ "name": null,
54107
+ "ofType": {
54108
+ "kind": "OBJECT",
54109
+ "name": "Namespace_v1",
54110
+ "ofType": null
54111
+ }
54112
+ },
54113
+ "isDeprecated": false,
54114
+ "deprecationReason": null
54115
+ },
54116
+ {
54117
+ "name": "api_version",
54118
+ "description": null,
54119
+ "args": [],
54120
+ "type": {
54121
+ "kind": "SCALAR",
54122
+ "name": "String",
54123
+ "ofType": null
54124
+ },
54125
+ "isDeprecated": false,
54126
+ "deprecationReason": null
54127
+ },
54128
+ {
54129
+ "name": "kind",
54130
+ "description": null,
54131
+ "args": [],
54132
+ "type": {
54133
+ "kind": "NON_NULL",
54134
+ "name": null,
54135
+ "ofType": {
54136
+ "kind": "SCALAR",
54137
+ "name": "String",
54138
+ "ofType": null
54139
+ }
54140
+ },
54141
+ "isDeprecated": false,
54142
+ "deprecationReason": null
54143
+ },
54144
+ {
54145
+ "name": "name",
54146
+ "description": null,
54147
+ "args": [],
54148
+ "type": {
54149
+ "kind": "NON_NULL",
54150
+ "name": null,
54151
+ "ofType": {
54152
+ "kind": "SCALAR",
54153
+ "name": "String",
54154
+ "ofType": null
54155
+ }
54156
+ },
54157
+ "isDeprecated": false,
54158
+ "deprecationReason": null
54159
+ }
54160
+ ],
54161
+ "inputFields": null,
54162
+ "interfaces": [],
54163
+ "enumValues": null,
54164
+ "possibleTypes": null
54165
+ },
53919
54166
  {
53920
54167
  "kind": "OBJECT",
53921
54168
  "name": "AutomatedActionOpenshiftWorkloadRestart_v1",
reconcile/quay_base.py CHANGED
@@ -1,12 +1,24 @@
1
1
  from collections import namedtuple
2
- from typing import Any
2
+ from typing import Any, TypedDict
3
3
 
4
4
  from reconcile import queries
5
5
  from reconcile.utils.quay_api import QuayApi
6
6
  from reconcile.utils.secret_reader import SecretReader
7
7
 
8
8
  OrgKey = namedtuple("OrgKey", ["instance", "org_name"])
9
- QuayApiStore = dict[OrgKey, dict[str, Any]]
9
+
10
+
11
+ class OrgInfo(TypedDict):
12
+ url: str
13
+ api: QuayApi
14
+ push_token: dict[str, str] | None
15
+ teams: list[str]
16
+ managedRepos: bool
17
+ mirror: OrgKey | None
18
+ mirror_filters: dict[str, Any]
19
+
20
+
21
+ QuayApiStore = dict[OrgKey, OrgInfo]
10
22
 
11
23
 
12
24
  def get_quay_api_store() -> QuayApiStore:
@@ -49,14 +61,16 @@ def get_quay_api_store() -> QuayApiStore:
49
61
  else:
50
62
  push_token = None
51
63
 
52
- store[org_key] = {
64
+ org_info: OrgInfo = {
53
65
  "url": base_url,
54
66
  "api": QuayApi(token, org_name, base_url=base_url),
55
67
  "push_token": push_token,
56
- "teams": org_data.get("managedTeams"),
57
- "managedRepos": org_data.get("managedRepos"),
68
+ "teams": org_data.get("managedTeams") or [],
69
+ "managedRepos": bool(org_data.get("managedRepos")),
58
70
  "mirror": mirror,
59
71
  "mirror_filters": mirror_filters,
60
72
  }
61
73
 
74
+ store[org_key] = org_info
75
+
62
76
  return store
@@ -103,11 +103,16 @@ class QuayMirrorOrg:
103
103
 
104
104
  quay_api = org_info["api"]
105
105
  upstream_org_key = org_info["mirror"]
106
+ assert upstream_org_key is not None
106
107
  upstream_org = self.quay_api_store[upstream_org_key]
107
108
  upstream_quay_api = upstream_org["api"]
108
109
 
109
- username = upstream_org["push_token"]["user"]
110
- token = upstream_org["push_token"]["token"]
110
+ push_token = upstream_org["push_token"]
111
+
112
+ assert push_token is not None
113
+
114
+ username = push_token["user"]
115
+ token = push_token["token"]
111
116
 
112
117
  org_repos = [item["name"] for item in quay_api.list_images()]
113
118
  for repo in upstream_quay_api.list_images():
@@ -143,8 +148,11 @@ class QuayMirrorOrg:
143
148
  org_name = org_key.org_name
144
149
 
145
150
  server_url = org["url"]
146
- username = org["push_token"]["user"]
147
- password = org["push_token"]["token"]
151
+ push_token = org["push_token"]
152
+ assert push_token is not None
153
+
154
+ username = push_token["user"]
155
+ password = push_token["token"]
148
156
 
149
157
  for item in data:
150
158
  image = Image(
@@ -281,6 +289,8 @@ class QuayMirrorOrg:
281
289
  """
282
290
 
283
291
  push_token = self.quay_api_store[org_key]["push_token"]
292
+ assert push_token is not None
293
+
284
294
  username = push_token["user"]
285
295
  password = push_token["token"]
286
296
  return f"{username}:{password}"
reconcile/quay_repos.py CHANGED
@@ -230,6 +230,7 @@ def run(dry_run: bool) -> None:
230
230
  if org_info.get("mirror"):
231
231
  # ensure there are no circular mirror dependencies
232
232
  mirror_org_key = org_info["mirror"]
233
+ assert mirror_org_key is not None
233
234
  mirror_org = quay_api_store[mirror_org_key]
234
235
  if mirror_org.get("mirror"):
235
236
  logging.error(
@@ -29,7 +29,7 @@ class PasswordValidator:
29
29
  self._policy_flags = policy_flags
30
30
  self._mininum_length = minimum_length
31
31
 
32
- def validate(self, password: str):
32
+ def validate(self, password: str) -> None:
33
33
  errors: list[str] = []
34
34
 
35
35
  if len(password) < self._mininum_length:
@@ -1,3 +1,5 @@
1
+ from typing import Any
2
+
1
3
  import requests
2
4
 
3
5
 
@@ -8,17 +10,23 @@ class QuayTeamNotFoundError(Exception):
8
10
  class QuayApi:
9
11
  LIMIT_FOLLOWS = 15
10
12
 
11
- def __init__(self, token, organization, base_url="quay.io", timeout=60):
13
+ def __init__(
14
+ self,
15
+ token: str,
16
+ organization: str,
17
+ base_url: str = "quay.io",
18
+ timeout: int = 60,
19
+ ) -> None:
12
20
  self.token = token
13
21
  self.organization = organization
14
22
  self.auth_header = {"Authorization": "Bearer %s" % (token,)}
15
- self.team_members = {}
23
+ self.team_members: dict[str, Any] = {}
16
24
  self.api_url = f"https://{base_url}/api/v1"
17
25
 
18
26
  self._timeout = timeout
19
27
  """Timeout to use for HTTP calls to Quay (seconds)."""
20
28
 
21
- def list_team_members(self, team, **kwargs):
29
+ def list_team_members(self, team: str, **kwargs: Any) -> list[dict]:
22
30
  """
23
31
  List Quay team members.
24
32
 
@@ -52,12 +60,12 @@ class QuayApi:
52
60
 
53
61
  return members_list
54
62
 
55
- def user_exists(self, user):
63
+ def user_exists(self, user: str) -> bool:
56
64
  url = f"{self.api_url}/users/{user}"
57
65
  r = requests.get(url, headers=self.auth_header, timeout=self._timeout)
58
66
  return r.ok
59
67
 
60
- def remove_user_from_team(self, user, team):
68
+ def remove_user_from_team(self, user: str, team: str) -> bool:
61
69
  """Deletes an user from a team.
62
70
 
63
71
  :raises HTTPError if there are any problems with the request
@@ -80,7 +88,7 @@ class QuayApi:
80
88
 
81
89
  return True
82
90
 
83
- def add_user_to_team(self, user, team):
91
+ def add_user_to_team(self, user: str, team: str) -> bool:
84
92
  """Adds an user to a team.
85
93
 
86
94
  :raises HTTPError if there are any errors with the request
@@ -93,7 +101,9 @@ class QuayApi:
93
101
  r.raise_for_status()
94
102
  return True
95
103
 
96
- def create_or_update_team(self, team: str, role="member", description=None) -> None:
104
+ def create_or_update_team(
105
+ self, team: str, role: str = "member", description: str | None = None
106
+ ) -> None:
97
107
  """
98
108
  Create or update an Organization team.
99
109
 
@@ -117,7 +127,9 @@ class QuayApi:
117
127
  )
118
128
  r.raise_for_status()
119
129
 
120
- def list_images(self, images=None, page=None, count=0):
130
+ def list_images(
131
+ self, images: list | None = None, page: str | None = None, count: int = 0
132
+ ) -> list[dict[str, Any]]:
121
133
  """
122
134
  https://docs.quay.io/api/swagger/#!/repository/listRepos
123
135
 
@@ -156,7 +168,7 @@ class QuayApi:
156
168
  return self.list_images(images, next_page, count + 1)
157
169
  return images
158
170
 
159
- def repo_create(self, repo_name, description, public):
171
+ def repo_create(self, repo_name: str, description: str, public: str) -> None:
160
172
  """Creates a repository called repo_name with the given description
161
173
  and public flag.
162
174
 
@@ -180,14 +192,14 @@ class QuayApi:
180
192
  )
181
193
  r.raise_for_status()
182
194
 
183
- def repo_delete(self, repo_name):
195
+ def repo_delete(self, repo_name: str) -> None:
184
196
  url = f"{self.api_url}/repository/{self.organization}/{repo_name}"
185
197
 
186
198
  # perform request
187
199
  r = requests.delete(url, headers=self.auth_header, timeout=self._timeout)
188
200
  r.raise_for_status()
189
201
 
190
- def repo_update_description(self, repo_name, description):
202
+ def repo_update_description(self, repo_name: str, description: str) -> None:
191
203
  url = f"{self.api_url}/repository/{self.organization}/{repo_name}"
192
204
 
193
205
  params = {"description": description}
@@ -198,13 +210,13 @@ class QuayApi:
198
210
  )
199
211
  r.raise_for_status()
200
212
 
201
- def repo_make_public(self, repo_name):
213
+ def repo_make_public(self, repo_name: str) -> None:
202
214
  self._repo_change_visibility(repo_name, "public")
203
215
 
204
- def repo_make_private(self, repo_name):
216
+ def repo_make_private(self, repo_name: str) -> None:
205
217
  self._repo_change_visibility(repo_name, "private")
206
218
 
207
- def _repo_change_visibility(self, repo_name, visibility):
219
+ def _repo_change_visibility(self, repo_name: str, visibility: str) -> None:
208
220
  url = f"{self.api_url}/repository/{self.organization}/{repo_name}/changevisibility"
209
221
 
210
222
  params = {"visibility": visibility}
@@ -215,7 +227,7 @@ class QuayApi:
215
227
  )
216
228
  r.raise_for_status()
217
229
 
218
- def get_repo_team_permissions(self, repo_name, team):
230
+ def get_repo_team_permissions(self, repo_name: str, team: str) -> str | None:
219
231
  url = (
220
232
  f"{self.api_url}/repository/{self.organization}/"
221
233
  + f"{repo_name}/permissions/team/{team}"
@@ -231,7 +243,7 @@ class QuayApi:
231
243
 
232
244
  return r.json().get("role") or None
233
245
 
234
- def set_repo_team_permissions(self, repo_name, team, role):
246
+ def set_repo_team_permissions(self, repo_name: str, team: str, role: str) -> None:
235
247
  url = (
236
248
  f"{self.api_url}/repository/{self.organization}/"
237
249
  + f"{repo_name}/permissions/team/{team}"