5
5
import shlex
6
6
import os
7
7
import sys
8
+ import requests
8
9
from pathlib import Path
9
10
from packaging .version import Version
10
11
11
12
import textwrap
12
13
from typing import Any , Dict , List , Tuple
13
14
import click
14
15
import re
15
- import requests
16
16
from concurrent .futures import Future , ThreadPoolExecutor , as_completed
17
17
import cloup
18
18
from cloup .constraints import If , IsSet , accept_none , require_one
36
36
RESOURCES_MAPPING_FILE : str = os .path .join (SCHEMA_DIR , "__resources-mappings.json" )
37
37
38
38
39
- def _is_kind_and_namespaced (client : str , _data : Dict [str , Any ]) -> Dict [str , Any ]:
39
+ def _is_kind_and_namespaced (client : str , _key : str , _data : Dict [str , Any ]) -> Dict [str , Any ]:
40
40
x_kubernetes_group_version_kind = _data ["x-kubernetes-group-version-kind" ][0 ]
41
41
_kind = x_kubernetes_group_version_kind ["kind" ]
42
42
_group = x_kubernetes_group_version_kind .get ("group" )
43
43
_version = x_kubernetes_group_version_kind .get ("version" )
44
44
_group_and_version = f"{ _group } /{ _version } " if _group else _version
45
45
46
- if run_command (command = shlex .split (f"{ client } explain { _kind } " ), check = False , log_errors = False )[0 ]:
47
- namespaced = (
46
+ not_resource_dict = {"is_kind" : False , "kind" : _key }
47
+
48
+ # if explain command failed, this is not a resource
49
+ if not run_command (command = shlex .split (f"{ client } explain { _kind } " ), check = False , log_errors = False )[0 ]:
50
+ return not_resource_dict
51
+
52
+ # check if this as a valid version for the resource.
53
+ api_resources_base_cmd = f"bash -c '{ client } api-resources"
54
+
55
+ if run_command (
56
+ command = shlex .split (f"{ api_resources_base_cmd } | grep -w { _kind } | grep { _group_and_version } '" ),
57
+ check = False ,
58
+ log_errors = False ,
59
+ )[0 ]:
60
+ # Check if the resource if namespaced.
61
+ _data ["namespaced" ] = (
48
62
run_command (
49
63
command = shlex .split (
50
- f"bash -c ' { client } api-resources --namespaced | grep -w { _kind } | grep { _group_and_version } | wc -l'"
64
+ f"{ api_resources_base_cmd } --namespaced | grep -w { _kind } | grep { _group_and_version } | wc -l'"
51
65
),
52
66
check = False ,
67
+ log_errors = False ,
53
68
)[1 ].strip ()
54
69
== "1"
55
70
)
56
- _data ["namespaced" ] = namespaced
57
- return {"is_kind" : True , "kind" : _kind , "data" : _data }
71
+ return {"is_kind" : True , "kind" : _key , "data" : _data }
58
72
59
- return { "is_kind" : False , "kind" : _kind }
73
+ return not_resource_dict
60
74
61
75
62
76
def map_kind_to_namespaced (client : str ):
63
77
not_kind_file : str = os .path .join (SCHEMA_DIR , "__not-kind.txt" )
64
78
79
+ resources_mapping = read_resources_mapping_file ()
80
+
65
81
if os .path .isfile (not_kind_file ):
66
82
with open (not_kind_file ) as fd :
67
83
not_kind_list = fd .read ().split ("\n " )
@@ -71,37 +87,45 @@ def map_kind_to_namespaced(client: str):
71
87
with open (SCHEMA_DEFINITION_FILE ) as fd :
72
88
_definitions_json_data = json .load (fd )
73
89
74
- resources_mapping : Dict [Any , List [Any ]] = {}
75
-
76
90
_kind_data_futures : List [Future ] = []
77
91
with ThreadPoolExecutor () as executor :
78
- for _data in _definitions_json_data ["definitions" ].values ():
92
+ for _key , _data in _definitions_json_data ["definitions" ].items ():
79
93
_group_version_kind = _data .get ("x-kubernetes-group-version-kind" )
80
94
if not _group_version_kind :
81
95
continue
82
96
83
- if _group_version_kind [ 0 ][ "kind" ] in not_kind_list :
97
+ if _key in not_kind_list :
84
98
continue
85
99
86
- _kind_data_futures .append (executor .submit (_is_kind_and_namespaced , client = client , _data = _data ))
100
+ _kind_data_futures .append (executor .submit (_is_kind_and_namespaced , client = client , _key = _key , _data = _data ))
87
101
102
+ _temp_resources_mappings : Dict [Any , Any ] = {}
88
103
for res in as_completed (_kind_data_futures ):
89
104
_res = res .result ()
105
+ # _res["kind"] is group.version.kind, set only kind as key in the final dict
106
+ kind_key = _res ["kind" ].rsplit ("." , 1 )[- 1 ].lower ()
107
+
90
108
if _res ["is_kind" ]:
91
- resources_mapping .setdefault (_res [ "kind" ]. lower () , []).append (_res ["data" ])
109
+ _temp_resources_mappings .setdefault (kind_key , []).append (_res ["data" ])
92
110
else :
93
111
not_kind_list .append (_res ["kind" ])
94
112
113
+ # Update the resources mapping dict with the one that we filled to avoid duplication in the lists
114
+ resources_mapping .update (_temp_resources_mappings )
115
+
95
116
with open (RESOURCES_MAPPING_FILE , "w" ) as fd :
96
- json .dump (resources_mapping , fd )
117
+ json .dump (resources_mapping , fd , indent = 4 )
97
118
98
119
with open (not_kind_file , "w" ) as fd :
99
120
fd .writelines ("\n " .join (not_kind_list ))
100
121
101
122
102
123
def read_resources_mapping_file () -> Dict [Any , Any ]:
103
- with open (RESOURCES_MAPPING_FILE ) as fd :
104
- return json .load (fd )
124
+ try :
125
+ with open (RESOURCES_MAPPING_FILE ) as fd :
126
+ return json .load (fd )
127
+ except (FileNotFoundError , json .JSONDecodeError ):
128
+ return {}
105
129
106
130
107
131
def get_server_version (client : str ):
@@ -142,7 +166,7 @@ def update_kind_schema():
142
166
143
167
if not run_command (command = shlex .split ("which openapi2jsonschema" ), check = False , log_errors = False )[0 ]:
144
168
LOGGER .error (
145
- f"{ openapi2jsonschema_str } not found. Install it using `pipx install --python python3.9 openapi2jsonschema`"
169
+ f"{ openapi2jsonschema_str } not found. Install it using `pipx install --python python3.9 openapi2jsonschema`"
146
170
)
147
171
sys .exit (1 )
148
172
0 commit comments