Skip to content

Commit 26404e6

Browse files
Merge pull request #1018 from oracle/develop-k8s-model
Support hyphenated lists in kubernetes section of WDT model
2 parents 9d4a8d0 + b2652f0 commit 26404e6

File tree

17 files changed

+476
-13783
lines changed

17 files changed

+476
-13783
lines changed

core/src/main/python/wlsdeploy/json/json_translator.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2017, 2020, Oracle Corporation and/or its affiliates.
2+
Copyright (c) 2017, 2021, Oracle Corporation and/or its affiliates.
33
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
44
55
This model provider translation classes that convert between JSON and Python Dictionaries.
@@ -18,6 +18,7 @@
1818
import oracle.weblogic.deploy.json.JsonTranslator as JJsonTranslator
1919

2020
from wlsdeploy.logging.platform_logger import PlatformLogger
21+
from wlsdeploy.util.boolean_value import BooleanValue
2122
import wlsdeploy.exception.exception_helper as exception_helper
2223

2324
# Unlike with yaml files, JSON files do not allow comments. remove from file
@@ -202,7 +203,7 @@ def _write_list_to_json_file(self, alist, writer, indent=''):
202203
writer.println()
203204
if isinstance(value, dict):
204205
writer.write(list_indent)
205-
self._write_dictionary_to_json_file(value, writer, indent)
206+
self._write_dictionary_to_json_file(value, writer, list_indent)
206207
else:
207208
writer.write(list_indent)
208209
writer.write(_format_json_value(value))
@@ -239,6 +240,8 @@ def _format_json_value(value):
239240
builder = StringBuilder()
240241
if type(value) == bool:
241242
builder.append(JBoolean.toString(value))
243+
elif isinstance(value, BooleanValue):
244+
builder.append(value.get_string_value())
242245
elif isinstance(value, types.StringTypes):
243246
builder.append('"').append(_escape_text(value.strip())).append('"')
244247
else:

core/src/main/python/wlsdeploy/tool/extract/domain_resource_extractor.py

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
from wlsdeploy.aliases.alias_constants import PASSWORD_TOKEN
1212
from wlsdeploy.aliases.model_constants import CLUSTER
1313
from wlsdeploy.aliases.model_constants import DEFAULT_WLS_DOMAIN_NAME
14-
from wlsdeploy.aliases.model_constants import KUBERNETES
1514
from wlsdeploy.aliases.model_constants import MODEL_LIST_DELIMITER
1615
from wlsdeploy.aliases.model_constants import NAME
1716
from wlsdeploy.exception import exception_helper
1817
from wlsdeploy.exception.expection_types import ExceptionType
1918
from wlsdeploy.tool.extract import wko_schema_helper
2019
from wlsdeploy.tool.util import k8s_helper
2120
from wlsdeploy.util import dictionary_utils
21+
from wlsdeploy.util.boolean_value import BooleanValue
2222
from wlsdeploy.util.model_translator import PythonToFile
2323

2424
API_VERSION = 'apiVersion'
@@ -50,7 +50,8 @@
5050
DEFAULT_IMAGE_PULL_SECRETS = PASSWORD_TOKEN
5151
DEFAULT_SOURCE_TYPE = 'Image'
5252

53-
MULTI_KEYS = {
53+
# deprecated - used for "named object list" format
54+
OBJECT_NAME_ATTRIBUTES = {
5455
'spec/adminServer/adminService/channels': 'channelName',
5556
'spec/clusters': 'clusterName'
5657
}
@@ -71,9 +72,6 @@ def __init__(self, model, model_context, logger):
7172
return
7273

7374
def extract(self):
74-
"""
75-
Deploy resource model elements at the domain level, including multi-tenant elements.
76-
"""
7775
_method_name = 'extract'
7876

7977
resource_file = self._model_context.get_domain_resource_file()
@@ -93,7 +91,6 @@ def extract(self):
9391

9492
# write the resource file structure to the output file
9593
writer = PythonToFile(resource_dict)
96-
writer.set_yaml_hyphenate_yaml_lists(True)
9794
writer.write_to_file(resource_file)
9895
return
9996

@@ -108,42 +105,35 @@ def _create_domain_resource_dictionary(self):
108105

109106
schema = wko_schema_helper.get_domain_resource_schema(ExceptionType.DEPLOY)
110107

111-
model_path = KUBERNETES + ":"
112-
self._process_folder(kubernetes_map, schema, resource_dict, None, model_path)
108+
self._process_object(kubernetes_map, schema, resource_dict, None)
113109
return resource_dict
114110

115-
def _process_folder(self, model_dict, schema_folder, target_dict, schema_path, model_path):
111+
def _process_object(self, model_dict, schema_folder, target_dict, schema_path):
116112
"""
117113
Transfer folders and attributes from the model dictionary to the target domain resource dictionary.
118114
:param model_dict: the source model dictionary
119115
:param schema_folder: the schema for this folder
120116
:param target_dict: the target dictionary for the domain resource file.
121-
:param schema_path: the path of schema elements (no multi-element names), used for supported check
122-
:param model_path: the path of model elements (including multi-element names), used for logging
117+
:param schema_path: the path of schema elements, used for supported check
123118
"""
124119
folder_properties = schema_folder["properties"]
125120

126121
for key, model_value in model_dict.items():
127122
properties = folder_properties[key]
128123

129-
if wko_schema_helper.is_single_folder(properties):
130-
# single object instance
124+
if wko_schema_helper.is_single_object(properties):
131125
next_schema_path = wko_schema_helper.append_path(schema_path, key)
132-
next_model_path = model_path + "/" + key
133126
if not wko_schema_helper.is_unsupported_folder(next_schema_path):
134127
next_target_dict = PyOrderedDict()
135128
target_dict[key] = next_target_dict
136-
self._process_folder(model_value, properties, next_target_dict, next_schema_path,
137-
next_model_path)
129+
self._process_object(model_value, properties, next_target_dict, next_schema_path)
138130

139-
elif wko_schema_helper.is_multiple_folder(properties):
140-
# multiple object instances
131+
elif wko_schema_helper.is_object_array(properties):
141132
next_schema_path = wko_schema_helper.append_path(schema_path, key)
142-
next_model_path = model_path + "/" + key
143133
if not wko_schema_helper.is_unsupported_folder(next_schema_path):
144134
item_info = wko_schema_helper.get_array_item_info(properties)
145135
target_dict[key] = \
146-
self._process_multiple_folder(model_value, item_info, next_schema_path, next_model_path)
136+
self._process_object_array(model_value, item_info, next_schema_path)
147137

148138
elif wko_schema_helper.is_simple_map(properties):
149139
# map of key / value pairs
@@ -154,30 +144,35 @@ def _process_folder(self, model_dict, schema_folder, target_dict, schema_path, m
154144
property_type = wko_schema_helper.get_type(properties)
155145
target_dict[key] = _get_target_value(model_value, property_type)
156146

157-
def _process_multiple_folder(self, model_value, item_info, schema_path, model_path):
147+
def _process_object_array(self, model_value, item_info, schema_path):
158148
"""
159-
Process a multiple-element model section.
160-
There should be a dictionary of names, each containing a sub-folder.
149+
Process an array of objects.
161150
:param model_value: the model contents for a folder
162151
:param item_info: describes the contents of the sub-folder for each element
163-
:param schema_path: the path of schema elements (no multi-element names), used for supported check
164-
:param model_path: the path of model elements (including multi-element names), used for logging
152+
:param schema_path: the path of schema elements, used for supported check
165153
"""
166154
child_list = list()
167-
for name in model_value:
168-
name_map = model_value[name]
169-
next_target_dict = PyOrderedDict()
170-
next_model_path = model_path + "/" + name
171-
self._process_folder(name_map, item_info, next_target_dict, schema_path, next_model_path)
172-
173-
# see if the model name should become an attribute in the target dict
174-
mapped_name = get_mapped_key(schema_path)
175-
properties = wko_schema_helper.get_properties(item_info)
176-
if (mapped_name in properties.keys()) and (mapped_name not in next_target_dict.keys()):
177-
_add_to_top(next_target_dict, mapped_name, name)
178155

156+
# deprecated "named object list" format - warning was issued in validator
157+
if isinstance(model_value, dict):
158+
for name in model_value:
159+
object_map = model_value[name]
160+
next_target_dict = PyOrderedDict()
161+
self._process_object(object_map, item_info, next_target_dict, schema_path)
162+
163+
# see if the model name should become an attribute in the target dict
164+
mapped_name = get_mapped_key(schema_path)
165+
properties = wko_schema_helper.get_properties(item_info)
166+
if (mapped_name in properties.keys()) and (mapped_name not in next_target_dict.keys()):
167+
_add_to_top(next_target_dict, mapped_name, name)
168+
child_list.append(next_target_dict)
169+
return child_list
170+
# end deprecated
171+
172+
for object_map in model_value:
173+
next_target_dict = PyOrderedDict()
174+
self._process_object(object_map, item_info, next_target_dict, schema_path)
179175
child_list.append(next_target_dict)
180-
181176
return child_list
182177

183178
def _update_resource_dictionary(self, resource_dict):
@@ -304,7 +299,7 @@ def _get_target_value(model_value, type_name):
304299
if type_name == 'boolean':
305300
# the model values can be true, false, 1, 0, etc.
306301
# target boolean values must be 'true' or 'false'
307-
return alias_utils.convert_to_type('boolean', model_value)
302+
return BooleanValue(model_value)
308303

309304
if type_name == 'array':
310305
# the model values can be 'abc,123'.
@@ -337,16 +332,17 @@ def _add_secrets(folder, secrets, domain_uid):
337332
secrets.append(secret_name)
338333

339334

335+
# deprecated
340336
def get_mapped_key(schema_path):
341337
"""
342-
Because the WDT model does not support hyphenated lists, the name of each item in a
338+
For the deprecated "named object list format", the name of each item in a
343339
multiple folder sometimes corresponds to one of its attributes, usually "name".
344340
If a different attribute name is used for the path, return that name.
345341
If the default 'name' is returned, caller should verify that it is an available attribute.
346342
:param schema_path: the slash-delimited path of the elements (no multi-element names)
347343
:return: the attribute key to be used
348344
"""
349-
mapped_key = dictionary_utils.get_element(MULTI_KEYS, schema_path)
345+
mapped_key = dictionary_utils.get_element(OBJECT_NAME_ATTRIBUTES, schema_path)
350346
if mapped_key is not None:
351347
return mapped_key
352348
return 'name'

core/src/main/python/wlsdeploy/tool/extract/wko_schema_helper.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2020, Oracle Corporation and/or its affiliates.
2+
Copyright (c) 2020, 2021, Oracle and/or its affiliates.
33
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
44
"""
55
from oracle.weblogic.deploy.util import FileUtils
@@ -15,11 +15,17 @@
1515
DOMAIN_RESOURCE_SCHEMA_PATH = 'oracle/weblogic/deploy/wko/' + DOMAIN_RESOURCE_SCHEMA_FILE
1616

1717
SIMPLE_TYPES = [
18+
'integer',
1819
'number',
1920
'string',
2021
'boolean'
2122
]
2223

24+
OBJECT_TYPES = [
25+
'object',
26+
None
27+
]
28+
2329
UNSUPPORTED_FOLDERS = [
2430
'status',
2531
'metadata/initializers',
@@ -56,32 +62,37 @@ def get_domain_resource_schema(exception_type=ExceptionType.DEPLOY):
5662
return schema
5763

5864

59-
def is_single_folder(schema_map):
65+
def is_single_object(schema_map):
6066
"""
61-
Return True if the schema map describes a single folder.
67+
Return True if the schema map describes a single object.
6268
:param schema_map: the schema map to be examined
63-
:return: True if the map identifies a single folder
69+
:return: True if the map identifies a single object
6470
"""
6571
property_type = get_type(schema_map)
66-
if property_type == "object":
72+
if property_type in OBJECT_TYPES:
6773
return get_map_element_type(schema_map) is None
6874
return False
6975

7076

71-
def is_multiple_folder(schema_map):
77+
def is_object_array(schema_map):
7278
"""
73-
Return True if the schema map identifies a multiple folder.
79+
Return True if the schema map describes an object array.
7480
:param schema_map: the schema map to be examined
75-
:return: True if the map identifies a multiple folder
81+
:return: True if the map identifies an object array
7682
"""
7783
property_type = get_type(schema_map)
7884
if property_type == "array":
79-
return get_array_element_type(schema_map) == "object"
85+
return get_array_element_type(schema_map) in OBJECT_TYPES
8086
return False
8187

8288

83-
def is_folder(schema_map):
84-
return is_single_folder(schema_map) or is_multiple_folder(schema_map)
89+
def is_object_type(schema_map):
90+
"""
91+
Return True if the schema map describes an object or object array.
92+
:param schema_map: the schema map to be examined
93+
:return: True if the map identifies an object or object array
94+
"""
95+
return is_single_object(schema_map) or is_object_array(schema_map)
8596

8697

8798
def is_simple_map(schema_map):
@@ -91,7 +102,7 @@ def is_simple_map(schema_map):
91102
:return: True if the map identifies a simple map
92103
"""
93104
property_type = get_type(schema_map)
94-
if property_type == "object":
105+
if property_type in OBJECT_TYPES:
95106
return get_map_element_type(schema_map) is not None
96107
return False
97108

@@ -104,10 +115,20 @@ def is_simple_array(schema_map):
104115
"""
105116
property_type = get_type(schema_map)
106117
if property_type == "array":
107-
return get_array_element_type(schema_map) != "object"
118+
return get_array_element_type(schema_map) not in OBJECT_TYPES
108119
return False
109120

110121

122+
def is_simple_type(schema_map):
123+
"""
124+
Return True if the schema map describes a simple type.
125+
:param schema_map: the schema map to be examined
126+
:return: True if the map identifies a simple type
127+
"""
128+
property_type = get_type(schema_map)
129+
return property_type in SIMPLE_TYPES
130+
131+
111132
def get_array_element_type(schema_map):
112133
item_info = get_array_item_info(schema_map)
113134
return get_type(item_info)
@@ -123,7 +144,8 @@ def get_array_item_info(schema_map):
123144

124145

125146
def get_properties(schema_map):
126-
return dictionary_utils.get_element(schema_map, "properties")
147+
properties = dictionary_utils.get_element(schema_map, "properties")
148+
return properties or {}
127149

128150

129151
def get_type(schema_map):

0 commit comments

Comments
 (0)