class PrepareModel:
    """
      This is the main driver for the caller.  It compares two model files whether they are json or yaml format.
    """
    def __init__(self, model_files, model_context, logger, output_dir=None):
        self.model_files = model_files
        self.output_dir = output_dir
        self.model_context = model_context
        self._aliases = Aliases(model_context=model_context, wlst_mode=WlstModes.OFFLINE)
        self._alias_helper = AliasHelper(self._aliases, logger, ExceptionType.COMPARE)
        self._logger = logger
        self._name_tokens_location = LocationContext()
        self._name_tokens_location.add_name_token('DOMAIN', "testdomain")
        self.current_dict = None
        self.cache =  OrderedDict()
        self.secrets_to_generate = sets.Set()

    def __walk_model_section(self, model_section_key, model_dict, valid_section_folders):
        _method_name = '__validate_model_section'

        if model_section_key not in model_dict.keys():
            return

        # only specific top-level sections have attributes
        attribute_location = self._alias_helper.get_model_section_attribute_location(model_section_key)

        valid_attr_infos = []
        path_tokens_attr_keys = []

        if attribute_location is not None:
            valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(attribute_location)
            path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names(attribute_location)

        model_section_dict = model_dict[model_section_key]
        for section_dict_key, section_dict_value in model_section_dict.iteritems():
            # section_dict_key is either the name of a folder in the
            # section, or the name of an attribute in the section.
            validation_location = LocationContext()

            model_folder_path = model_section_key + ":/"
            if section_dict_key in valid_attr_infos:
                # section_dict_key is the name of an attribute in the section
                self.__walk_attribute(section_dict_key, section_dict_value, valid_attr_infos,
                                      path_tokens_attr_keys, model_folder_path, attribute_location)

            elif section_dict_key in valid_section_folders:
                # section_dict_key is a folder under the model section

                # Append section_dict_key to location context
                validation_location.append_location(section_dict_key)

                # Call self.__validate_section_folder() passing in section_dict_value as the model_node to process
                self.__walk_section_folder(section_dict_value, validation_location)


    def __walk_section_folder(self, model_node, validation_location):
        _method_name = '__validate_section_folder'

        model_folder_path = self._alias_helper.get_model_folder_path(validation_location)

        if self._alias_helper.supports_multiple_mbean_instances(validation_location):

            for name in model_node:
                expanded_name = name

                new_location = LocationContext(validation_location)

                name_token = self._alias_helper.get_name_token(new_location)

                if name_token is not None:
                    new_location.add_name_token(name_token, expanded_name)

                value_dict = model_node[name]

                self.__walk_model_node(value_dict, new_location)

        elif self._alias_helper.requires_artificial_type_subfolder_handling(validation_location):

            for name in model_node:
                expanded_name = name

                new_location = LocationContext(validation_location)

                name_token = self._alias_helper.get_name_token(new_location)

                if name_token is not None:
                    new_location.add_name_token(name_token, expanded_name)

                value_dict = model_node[name]

                self.__walk_model_node(value_dict, new_location)

        else:
            name_token = self._alias_helper.get_name_token(validation_location)

            if name_token is not None:
                name = self._name_tokens_location.get_name_for_token(name_token)

                if name is None:
                    name = '%s-0' % name_token

                validation_location.add_name_token(name_token, name)

            self.__walk_model_node(model_node, validation_location)

    def __walk_model_node(self, model_node, validation_location):
        _method_name = '__process_model_node'

        valid_folder_keys = self._alias_helper.get_model_subfolder_names(validation_location)
        valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(validation_location)
        model_folder_path = self._alias_helper.get_model_folder_path(validation_location)

        for key, value in model_node.iteritems():

            if key in valid_folder_keys:
                new_location = LocationContext(validation_location).append_location(key)

                if self._alias_helper.is_artificial_type_folder(new_location):
                    # key is an ARTIFICIAL_TYPE folder
                    valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(new_location)

                    self.__walk_attributes(value, valid_attr_infos, new_location)
                else:
                    self.__walk_section_folder(value, new_location)

            elif key in valid_attr_infos:
                # aliases.get_model_attribute_names_and_types(location) filters out
                # attributes that ARE NOT valid in the wlst_version being used, so if
                # we're in this section of code we know key is a bonafide "valid" attribute
                valid_data_type = valid_attr_infos[key]
                if valid_data_type in ['properties']:
                    valid_prop_infos = {}
                    properties = validation_utils.get_properties(value)
                    self.__walk_properties(properties, valid_prop_infos, validation_location)

                else:
                    path_tokens_attr_keys = \
                        self._alias_helper.get_model_uses_path_tokens_attribute_names(validation_location)

                    self.__walk_attribute(key, value, valid_attr_infos, path_tokens_attr_keys, model_folder_path,
                                          validation_location)

    def __walk_attributes(self, attributes_dict, valid_attr_infos, validation_location):
        _method_name = '__validate_attributes'

        path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names(validation_location)

        model_folder_path = self._alias_helper.get_model_folder_path(validation_location)

        for attribute_name, attribute_value in attributes_dict.iteritems():
            self.__walk_attribute(attribute_name, attribute_value, valid_attr_infos, path_tokens_attr_keys,
                                  model_folder_path, validation_location)

    def __walk_attribute(self, attribute_name, attribute_value, valid_attr_infos, path_tokens_attr_keys,
                         model_folder_path, validation_location):
        _method_name = '__validate_attribute'

        if attribute_name in valid_attr_infos:
            expected_data_type = valid_attr_infos[attribute_name]

            if expected_data_type == 'password':
                self.__substitute_password_with_token(model_folder_path, attribute_name, validation_location)

        self._logger.exiting(class_name=_class_name, method_name=_method_name)

    def __walk_properties(self, properties_dict, valid_prop_infos, validation_location):
        _method_name = '__walk_properties'

        for property_name, property_value in properties_dict.iteritems():
            valid_prop_infos[property_name] = validation_utils.get_python_data_type(property_value)
            self.__walk_property(property_name, property_value, valid_prop_infos, validation_location)


    def __walk_property(self, property_name, property_value, valid_prop_infos, model_folder_path, validation_location):

        _method_name = '__walk_property'

        self._logger.entering(property_name, property_value, str(valid_prop_infos), model_folder_path,
                              class_name=_class_name, method_name=_method_name)

        if property_name in valid_prop_infos:
            expected_data_type = valid_prop_infos[property_name]
            if expected_data_type == 'password':
                self.__substitute_password_with_token(model_folder_path, property_name, validation_location)


    def __format_variable_name(self, location, attribute):
        _method_name = '__format_variable_name'
        def __traverse_location(iterate_location, name_list, last_folder=None, last_folder_short=None):
            current_folder = iterate_location.get_current_model_folder()
            if current_folder == model_constants.DOMAIN:
                if last_folder is not None:
                    # If a short name is not defined for the top level folder, use the full name
                    if len(last_folder_short) == 0:
                        last_folder_short = last_folder
                    name_list.insert(0, last_folder_short)
            else:
                current_folder = iterate_location.get_current_model_folder()
                short_folder = self._aliases.get_folder_short_name(iterate_location)
                if last_folder_short is not None:
                    name_list.insert(0, last_folder_short)
                try:
                    if not self._aliases.is_artificial_type_folder(location) and \
                            (self._aliases.supports_multiple_mbean_instances(iterate_location) or
                             self._aliases.is_custom_folder_allowed(iterate_location)):
                        name_token = self._aliases.get_name_token(iterate_location)
                        name = iterate_location.get_name_for_token(name_token)
                        name_list.insert(0, name)
                        iterate_location.remove_name_token(name_token)
                    iterate_location.pop_location()
                except AliasException, ae:
                    self._logger.warning('WLSDPLY-19531', str(location), attribute, ae.getLocalizedMessage(),
                                    class_name=_class_name, method_name=_method_name)
                __traverse_location(iterate_location, name_list, current_folder, short_folder)
            return name_list

        short_list = __traverse_location(LocationContext(location), list())
        short_name = ''
        for node in short_list:
            if node is not None and len(node) > 0:
                short_name += node + '.'
        short_name += attribute
        _fake_name_replacement = re.compile('.fakename')
        _white_space_replacement = re.compile('\s')
        short_name = short_name.replace('/', '.')
        short_name = _white_space_replacement.sub('-', short_name)
        short_name = _fake_name_replacement.sub('', short_name)

        return short_name
示例#2
0
class Creator(object):
    """
    The base class used by the DomainCreator.
    """
    __class_name = 'Creator'

    def __init__(self,
                 model,
                 model_context,
                 aliases,
                 exception_type=ExceptionType.CREATE,
                 logger=PlatformLogger('wlsdeploy.create')):

        self.logger = logger
        self.aliases = aliases
        self._exception_type = exception_type
        self.alias_helper = AliasHelper(self.aliases, self.logger,
                                        exception_type)
        self.wlst_helper = WlstHelper(self.logger, exception_type)
        self.model = Model(model)
        self.model_context = model_context
        self.wls_helper = WebLogicHelper(self.logger)
        self.attribute_setter = AttributeSetter(self.aliases, self.logger,
                                                exception_type)
        self.custom_folder_helper = CustomFolderHelper(self.aliases,
                                                       self.logger,
                                                       self.model_context,
                                                       exception_type)

        # Must be initialized by the subclass since only it has
        # the knowledge required to compute the domain name.
        self.archive_helper = None
        self.files_to_extract_from_archive = list()
        return

    def _create_named_mbeans(self,
                             type_name,
                             model_nodes,
                             base_location,
                             log_created=False):
        """
        Create the specified type of MBeans that support multiple instances in the specified location.
        :param type_name: the model folder type
        :param model_nodes: the model dictionary of the specified model folder type
        :param base_location: the base location object to use to create the MBeans
        :param log_created: whether or not to log created at INFO level, by default it is logged at the FINE level
        :raises: CreateException: if an error occurs
        """
        _method_name = '_create_named_mbeans'

        self.logger.entering(type_name,
                             str(base_location),
                             log_created,
                             class_name=self.__class_name,
                             method_name=_method_name)
        if model_nodes is None or len(
                model_nodes) == 0 or not self._is_type_valid(
                    base_location, type_name):
            return

        location = LocationContext(base_location).append_location(type_name)
        self._process_flattened_folder(location)

        token_name = self.alias_helper.get_name_token(location)
        create_path = self.alias_helper.get_wlst_create_path(location)
        list_path = self.alias_helper.get_wlst_list_path(location)
        existing_folder_names = self._get_existing_folders(list_path)
        for model_name in model_nodes:
            name = self.wlst_helper.get_quoted_name_for_wlst(model_name)

            if token_name is not None:
                location.add_name_token(token_name, name)

            wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(
                location)
            if wlst_name not in existing_folder_names:
                if log_created:
                    self.logger.info('WLSDPLY-12100',
                                     type_name,
                                     name,
                                     class_name=self.__class_name,
                                     method_name=_method_name)
                else:
                    self.logger.fine('WLSDPLY-12100',
                                     type_name,
                                     name,
                                     class_name=self.__class_name,
                                     method_name=_method_name)
                self.wlst_helper.create_and_cd(self.alias_helper, wlst_type,
                                               wlst_name, location,
                                               create_path)
            else:
                if log_created:
                    self.logger.info('WLSDPLY-12101',
                                     type_name,
                                     name,
                                     class_name=self.__class_name,
                                     method_name=_method_name)
                else:
                    self.logger.fine('WLSDPLY-12101',
                                     type_name,
                                     name,
                                     class_name=self.__class_name,
                                     method_name=_method_name)

                attribute_path = self.alias_helper.get_wlst_attributes_path(
                    location)
                self.wlst_helper.cd(attribute_path)

            child_nodes = dictionary_utils.get_dictionary_element(
                model_nodes, name)
            self._process_child_nodes(location, child_nodes)

        self.logger.exiting(class_name=self.__class_name,
                            method_name=_method_name)
        return

    def _create_mbean(self,
                      type_name,
                      model_nodes,
                      base_location,
                      log_created=False):
        """
        Create the specified type of MBean that support a single instance in the specified location.
        :param type_name: the model folder type
        :param model_nodes: the model dictionary of the specified model folder type
        :param base_location: the base location object to use to create the MBean
        :param log_created: whether or not to log created at INFO level, by default it is logged at the FINE level
        :raises: CreateException: if an error occurs
        """
        _method_name = '_create_mbean'

        self.logger.entering(type_name,
                             str(base_location),
                             log_created,
                             class_name=self.__class_name,
                             method_name=_method_name)
        if model_nodes is None or len(
                model_nodes) == 0 or not self._is_type_valid(
                    base_location, type_name):
            return

        location = LocationContext(base_location).append_location(type_name)
        result, message = self.alias_helper.is_version_valid_location(location)
        if result == ValidationCodes.VERSION_INVALID:
            self.logger.warning('WLSDPLY-12123',
                                message,
                                class_name=self.__class_name,
                                method_name=_method_name)
            return

        create_path = self.alias_helper.get_wlst_create_path(location)
        existing_folder_names = self._get_existing_folders(create_path)

        mbean_type, mbean_name = self.alias_helper.get_wlst_mbean_type_and_name(
            location)

        token_name = self.alias_helper.get_name_token(location)
        if token_name is not None:
            if self.alias_helper.requires_unpredictable_single_name_handling(
                    location):
                existing_subfolder_names = deployer_utils.get_existing_object_list(
                    location, self.alias_helper)
                if len(existing_subfolder_names) > 0:
                    mbean_name = existing_subfolder_names[0]

            location.add_name_token(token_name, mbean_name)

        self._process_flattened_folder(location)
        if mbean_type not in existing_folder_names:
            if log_created:
                self.logger.info('WLSDPLY-12102',
                                 type_name,
                                 class_name=self.__class_name,
                                 method_name=_method_name)
            else:
                self.logger.fine('WLSDPLY-12102',
                                 type_name,
                                 class_name=self.__class_name,
                                 method_name=_method_name)

            self.wlst_helper.create_and_cd(self.alias_helper, mbean_type,
                                           mbean_name, location, create_path)
        else:
            if log_created:
                self.logger.info('WLSDPLY-20013',
                                 type_name,
                                 class_name=self.__class_name,
                                 method_name=_method_name)
            else:
                self.logger.fine('WLSDPLY-12102',
                                 type_name,
                                 class_name=self.__class_name,
                                 method_name=_method_name)

            attribute_path = self.alias_helper.get_wlst_attributes_path(
                location)
            self.wlst_helper.cd(attribute_path)

        self._process_child_nodes(location, model_nodes)
        self.logger.exiting(class_name=self.__class_name,
                            method_name=_method_name)
        return

    def _create_named_subtype_mbeans(self,
                                     type_name,
                                     model_nodes,
                                     base_location,
                                     log_created=False):
        """
        Create the specified type of MBeans that support multiple instances, and require an artificial subtype
        layer after each name.
        There is no default behavior for this method. Sub-classes (currently only SecurityProviderCreator) will
        implement specialized behavior.
        :param type_name: the model folder type
        :param model_nodes: the model dictionary of the specified model folder type
        :param base_location: the base location object to use to create the MBeans
        :param log_created: whether or not to log created at INFO level, by default it is logged at the FINE level
        :raises: CreateException: if an error occurs
        """
        return

    def _create_subfolders(self, location, model_nodes):
        """
        Create the child MBean folders at the specified location.
        :param location: the location
        :param model_nodes: the model dictionary
        :raises: CreateException: if an error occurs
        """
        _method_name = '_create_subfolders'

        self.logger.entering(location.get_folder_path(),
                             class_name=self.__class_name,
                             method_name=_method_name)
        model_subfolder_names = self.alias_helper.get_model_subfolder_names(
            location)
        for key in model_nodes:
            if key in model_subfolder_names:
                subfolder_nodes = model_nodes[key]
                # don't check for empty subfolder nodes here, some create methods allow them

                sub_location = LocationContext(location).append_location(key)

                if self.alias_helper.requires_artificial_type_subfolder_handling(
                        sub_location):
                    self.logger.finest('WLSDPLY-12116',
                                       key,
                                       str(sub_location),
                                       subfolder_nodes,
                                       class_name=self.__class_name,
                                       method_name=_method_name)
                    self._create_named_subtype_mbeans(key, subfolder_nodes,
                                                      location, True)
                elif self.alias_helper.supports_multiple_mbean_instances(
                        sub_location):
                    self.logger.finest('WLSDPLY-12109',
                                       key,
                                       str(sub_location),
                                       subfolder_nodes,
                                       class_name=self.__class_name,
                                       method_name=_method_name)
                    self._create_named_mbeans(key, subfolder_nodes, location)
                elif self.alias_helper.is_artificial_type_folder(sub_location):
                    # these should have been handled inside create_named_subtype_mbeans
                    ex = exception_helper.create_create_exception(
                        'WLSDPLY-12120', str(sub_location), key, str(location))
                    self.logger.throwing(ex,
                                         class_name=self.__class_name,
                                         method_name=_method_name)
                    raise ex
                else:
                    self.logger.finest('WLSDPLY-12110',
                                       key,
                                       str(sub_location),
                                       subfolder_nodes,
                                       class_name=self.__class_name,
                                       method_name=_method_name)
                    self._create_mbean(key, subfolder_nodes, location)

        self.logger.exiting(class_name=self.__class_name,
                            method_name=_method_name)
        return

    def _process_child_nodes(self, location, model_nodes):
        """
        Process the model nodes at the specified location.
        The default behavior is to process attributes, then sub-folders.
        Sub-classes may override to reverse this order, or for other special processing.
        :param location: the location where the nodes should be applied
        :param model_nodes: the model dictionary of the nodes to be applied
        :raises: CreateException: if an error occurs
        """
        _method_name = '_process_child_nodes'

        self.logger.finest('WLSDPLY-12111',
                           self.alias_helper.get_model_folder_path(location),
                           self.wlst_helper.get_pwd(),
                           class_name=self.__class_name,
                           method_name=_method_name)
        self._set_attributes(location, model_nodes)
        self._create_subfolders(location, model_nodes)

    def _set_attributes(self, location, model_nodes):
        """
        Set the attributes for the MBean at the specified location.
        :param location: the location
        :param model_nodes: the model dictionary
        :raises: CreateException: if an error occurs
        """
        _method_name = '_set_attributes'

        model_attribute_names = self.alias_helper.get_model_attribute_names_and_types(
            location)
        password_attribute_names = self.alias_helper.get_model_password_type_attribute_names(
            location)
        set_method_map = self.alias_helper.get_model_mbean_set_method_attribute_names_and_types(
            location)
        uses_path_tokens_attribute_names = self.alias_helper.get_model_uses_path_tokens_attribute_names(
            location)
        model_folder_path = self.alias_helper.get_model_folder_path(location)
        pwd = self.wlst_helper.get_pwd()

        for key, value in model_nodes.iteritems():
            if key in model_attribute_names:
                if key in set_method_map:
                    self.logger.finest('WLSDPLY-12112',
                                       key,
                                       pwd,
                                       model_folder_path,
                                       class_name=self.__class_name,
                                       method_name=_method_name)
                    self._set_mbean_attribute(location, key, value,
                                              set_method_map)
                elif key in password_attribute_names:
                    self.logger.finest('WLSDPLY-12113',
                                       key,
                                       pwd,
                                       model_folder_path,
                                       class_name=self.__class_name,
                                       method_name=_method_name)
                    self._set_attribute(location,
                                        key,
                                        value,
                                        uses_path_tokens_attribute_names,
                                        masked=True)
                else:
                    self.logger.finest('WLSDPLY-12113',
                                       key,
                                       pwd,
                                       model_folder_path,
                                       class_name=self.__class_name,
                                       method_name=_method_name)
                    self._set_attribute(location, key, value,
                                        uses_path_tokens_attribute_names)
        return

    def _set_mbean_attribute(self, location, model_key, model_value,
                             set_method_map):
        """
        Set the attributes for the MBean that require an MBean value to set at the specified location.
        :param location: the location
        :param model_key: the model attribute name
        :param model_value: the model attribute value
        :param set_method_map: the set method map that maps the attribute names requiring MBean
                               values to the attribute setter method name
        :raises: CreateException: if an error occurs
        """
        _method_name = '_set_mbean_attribute'

        set_method_info = dictionary_utils.get_dictionary_element(
            set_method_map, model_key)
        set_method_name = dictionary_utils.get_element(set_method_info,
                                                       'set_method')

        if set_method_name is not None:
            try:
                self.logger.finest('WLSDPLY-12114',
                                   model_key,
                                   model_value,
                                   set_method_name,
                                   class_name=self.__class_name,
                                   method_name=_method_name)
                set_method = getattr(self.attribute_setter, set_method_name)
                set_method(location, model_key, model_value, None)
            except AttributeError, ae:
                ex = exception_helper.create_create_exception(
                    'WLSDPLY-12104',
                    set_method_name,
                    model_key,
                    self.alias_helper.get_model_folder_path(location),
                    error=ae)
                self.logger.throwing(ex,
                                     class_name=self.__class_name,
                                     method_name=_method_name)
                raise ex
        else:
示例#3
0
class PrepareModel:
    """
      This is the main driver for the caller.  It compares two model files whether they are json or yaml format.
    """
    def __init__(self, model_files, model_context, logger, output_dir=None):
        self.model_files = model_files
        self.output_dir = output_dir
        self.model_context = model_context
        self._aliases = Aliases(model_context=model_context,
                                wlst_mode=WlstModes.OFFLINE)
        self._alias_helper = AliasHelper(self._aliases, logger,
                                         ExceptionType.COMPARE)
        self._logger = logger
        self._name_tokens_location = LocationContext()
        self._name_tokens_location.add_name_token('DOMAIN', "testdomain")
        self.current_dict = None
        self.cache = OrderedDict()
        self.secrets_to_generate = sets.Set()

    def __walk_model_section(self, model_section_key, model_dict,
                             valid_section_folders):
        _method_name = '__validate_model_section'

        if model_section_key not in model_dict.keys():
            return

        # only specific top-level sections have attributes
        attribute_location = self._alias_helper.get_model_section_attribute_location(
            model_section_key)

        valid_attr_infos = []
        path_tokens_attr_keys = []

        if attribute_location is not None:
            valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(
                attribute_location)
            path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names(
                attribute_location)

        model_section_dict = model_dict[model_section_key]
        for section_dict_key, section_dict_value in model_section_dict.iteritems(
        ):
            # section_dict_key is either the name of a folder in the
            # section, or the name of an attribute in the section.
            validation_location = LocationContext()

            model_folder_path = model_section_key + ":/"
            if section_dict_key in valid_attr_infos:
                # section_dict_key is the name of an attribute in the section
                self.__walk_attribute(section_dict_key, section_dict_value,
                                      valid_attr_infos, path_tokens_attr_keys,
                                      model_folder_path, attribute_location)

            elif section_dict_key in valid_section_folders:
                # section_dict_key is a folder under the model section

                # Append section_dict_key to location context
                validation_location.append_location(section_dict_key)

                # Call self.__validate_section_folder() passing in section_dict_value as the model_node to process
                self.__walk_section_folder(section_dict_value,
                                           validation_location)

    def __walk_section_folder(self, model_node, validation_location):
        _method_name = '__validate_section_folder'

        model_folder_path = self._alias_helper.get_model_folder_path(
            validation_location)

        if self._alias_helper.supports_multiple_mbean_instances(
                validation_location):

            for name in model_node:
                expanded_name = name

                new_location = LocationContext(validation_location)

                name_token = self._alias_helper.get_name_token(new_location)

                if name_token is not None:
                    new_location.add_name_token(name_token, expanded_name)

                value_dict = model_node[name]

                self.__walk_model_node(value_dict, new_location)

        elif self._alias_helper.requires_artificial_type_subfolder_handling(
                validation_location):

            for name in model_node:
                expanded_name = name

                new_location = LocationContext(validation_location)

                name_token = self._alias_helper.get_name_token(new_location)

                if name_token is not None:
                    new_location.add_name_token(name_token, expanded_name)

                value_dict = model_node[name]

                self.__walk_model_node(value_dict, new_location)

        else:
            name_token = self._alias_helper.get_name_token(validation_location)

            if name_token is not None:
                name = self._name_tokens_location.get_name_for_token(
                    name_token)

                if name is None:
                    name = '%s-0' % name_token

                validation_location.add_name_token(name_token, name)

            self.__walk_model_node(model_node, validation_location)

    def __walk_model_node(self, model_node, validation_location):
        _method_name = '__process_model_node'

        valid_folder_keys = self._alias_helper.get_model_subfolder_names(
            validation_location)
        valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(
            validation_location)
        model_folder_path = self._alias_helper.get_model_folder_path(
            validation_location)

        for key, value in model_node.iteritems():

            if key in valid_folder_keys:
                new_location = LocationContext(
                    validation_location).append_location(key)

                if self._alias_helper.is_artificial_type_folder(new_location):
                    # key is an ARTIFICIAL_TYPE folder
                    valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(
                        new_location)

                    self.__walk_attributes(value, valid_attr_infos,
                                           new_location)
                else:
                    self.__walk_section_folder(value, new_location)

            elif key in valid_attr_infos:
                # aliases.get_model_attribute_names_and_types(location) filters out
                # attributes that ARE NOT valid in the wlst_version being used, so if
                # we're in this section of code we know key is a bonafide "valid" attribute
                valid_data_type = valid_attr_infos[key]
                if valid_data_type in ['properties']:
                    valid_prop_infos = {}
                    properties = validation_utils.get_properties(value)
                    self.__walk_properties(properties, valid_prop_infos,
                                           model_folder_path,
                                           validation_location)

                else:
                    path_tokens_attr_keys = \
                        self._alias_helper.get_model_uses_path_tokens_attribute_names(validation_location)

                    self.__walk_attribute(key, value, valid_attr_infos,
                                          path_tokens_attr_keys,
                                          model_folder_path,
                                          validation_location)

    def __walk_attributes(self, attributes_dict, valid_attr_infos,
                          validation_location):
        _method_name = '__validate_attributes'

        path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names(
            validation_location)

        model_folder_path = self._alias_helper.get_model_folder_path(
            validation_location)

        for attribute_name, attribute_value in attributes_dict.iteritems():
            self.__walk_attribute(attribute_name, attribute_value,
                                  valid_attr_infos, path_tokens_attr_keys,
                                  model_folder_path, validation_location)

    def __walk_attribute(self, attribute_name, attribute_value,
                         valid_attr_infos, path_tokens_attr_keys,
                         model_folder_path, validation_location):
        _method_name = '__walk_attribute'

        if attribute_name in valid_attr_infos:
            expected_data_type = valid_attr_infos[attribute_name]

            if (expected_data_type == 'password') or (attribute_name
                                                      == ADMIN_USERNAME):
                self.__substitute_password_with_token(model_folder_path,
                                                      attribute_name,
                                                      validation_location)

        self._logger.exiting(class_name=_class_name, method_name=_method_name)

    def __walk_properties(self, properties_dict, valid_prop_infos,
                          model_folder_path, validation_location):
        _method_name = '__walk_properties'

        for property_name, property_value in properties_dict.iteritems():
            valid_prop_infos[
                property_name] = validation_utils.get_python_data_type(
                    property_value)
            self.__walk_property(property_name, property_value,
                                 valid_prop_infos, model_folder_path,
                                 validation_location)

    def __walk_property(self, property_name, property_value, valid_prop_infos,
                        model_folder_path, validation_location):

        _method_name = '__walk_property'

        self._logger.entering(property_name,
                              property_value,
                              str(valid_prop_infos),
                              model_folder_path,
                              class_name=_class_name,
                              method_name=_method_name)

        if property_name in valid_prop_infos:
            expected_data_type = valid_prop_infos[property_name]
            if expected_data_type == 'password':
                self.__substitute_password_with_token(model_folder_path,
                                                      property_name,
                                                      validation_location)

    def __substitute_password_with_token(self, model_path, attribute_name,
                                         validation_location):
        """
        Add the secret for the specified attribute to the cache.
        If the target specifies credentials_method: secrets, substitute the secret token into the model.
        :param model_path: text representation of the model path
        :param attribute_name: the name of the attribute or (property)
        :param validation_location: the model location
        """
        model_path_tokens = model_path.split('/')
        tokens_length = len(model_path_tokens)
        variable_name = variable_injector_functions.format_variable_name(
            validation_location, attribute_name, self._aliases)
        if tokens_length > 1:
            credentials_method = self.model_context.get_target_configuration(
            ).get_credentials_method()

            # by default, don't do any assignment to attribute
            model_value = None

            # use attribute name for admin password
            if model_path_tokens[0] == 'domainInfo:' and model_path_tokens[
                    1] == '':
                cache_key = attribute_name
            else:
                cache_key = variable_name

            # for normal secrets, assign the secret name to the attribute
            if credentials_method == SECRETS_METHOD:
                model_value = target_configuration_helper.format_as_secret_token(
                    cache_key)
                self.cache[cache_key] = ''

            # for config override secrets, assign a placeholder password to the attribute.
            # config overrides will be used to override the value in the target domain.
            if credentials_method == CONFIG_OVERRIDES_SECRETS_METHOD:
                model_value = PASSWORD_PLACEHOLDER
                self.cache[cache_key] = ''

            if model_value is not None:
                p_dict = self.current_dict
                for index in range(0, len(model_path_tokens)):
                    token = model_path_tokens[index]
                    if token == '':
                        break
                    if token[-1] == ':':
                        token = token[:-1]
                    p_dict = p_dict[token]

                p_dict[attribute_name] = model_value

    def walk(self):
        """
        Replace password attributes in each model file with secret tokens, and write each model.
        Generate a script to create the required secrets.
        Create any additional output specified for the target environment.
        """
        _method_name = "walk"

        model_file_name = None

        try:
            model_file_list = self.model_files.split(',')
            for model_file in model_file_list:
                self.cache.clear()
                if os.path.splitext(model_file)[1].lower() == ".yaml":
                    model_file_name = model_file
                    FileToPython(model_file_name, True).parse()

                aliases = Aliases(model_context=self.model_context,
                                  wlst_mode=WlstModes.OFFLINE)

                validator = Validator(self.model_context,
                                      aliases,
                                      wlst_mode=WlstModes.OFFLINE)

                # Just merge and validate but without substitution
                model_dictionary = cla_helper.merge_model_files(
                    model_file_name, None)

                variable_file = self.model_context.get_variable_file()
                if not os.path.exists(variable_file):
                    variable_file = None

                return_code = validator.validate_in_tool_mode(
                    model_dictionary,
                    variables_file_name=variable_file,
                    archive_file_name=None)

                if return_code == Validator.ReturnCode.STOP:
                    self._logger.severe('WLSDPLY-05705', model_file_name)
                    return VALIDATION_FAIL

                self.current_dict = model_dictionary

                self.__walk_model_section(
                    model.get_model_domain_info_key(), self.current_dict,
                    aliases.get_model_section_top_level_folder_names(
                        DOMAIN_INFO))

                self.__walk_model_section(
                    model.get_model_topology_key(), self.current_dict,
                    aliases.get_model_topology_top_level_folder_names())

                self.__walk_model_section(
                    model.get_model_resources_key(), self.current_dict,
                    aliases.get_model_resources_top_level_folder_names())

                self.current_dict = self._apply_filter_and_inject_variable(
                    self.current_dict, self.model_context, validator)

                file_name = os.path.join(self.output_dir,
                                         os.path.basename(model_file_name))
                fos = JFileOutputStream(file_name, False)
                writer = JPrintWriter(fos, True)
                pty = PythonToYaml(self.current_dict)
                pty._write_dictionary_to_yaml_file(self.current_dict, writer)
                writer.close()

            self.cache.clear()
            for key in self.secrets_to_generate:
                self.cache[key] = ''

            # use a merged, substituted, filtered model to get domain name and create additional target output.
            full_model_dictionary = cla_helper.load_model(
                _program_name, self.model_context, self._alias_helper,
                "discover", WlstModes.OFFLINE)

            target_configuration_helper.generate_k8s_script(
                self.model_context, self.cache, full_model_dictionary)

            # create any additional outputs from full model dictionary
            target_configuration_helper.create_additional_output(
                Model(full_model_dictionary), self.model_context,
                self._alias_helper, ExceptionType.VALIDATE)

        except ValidateException, te:
            self._logger.severe('WLSDPLY-20009',
                                _program_name,
                                model_file_name,
                                te.getLocalizedMessage(),
                                error=te,
                                class_name=_class_name,
                                method_name=_method_name)
            ex = exception_helper.create_compare_exception(
                te.getLocalizedMessage(), error=te)
            self._logger.throwing(ex,
                                  class_name=_class_name,
                                  method_name=_method_name)
            return VALIDATION_FAIL
        except VariableException, ve:
            self._logger.severe('WLSDPLY-20009',
                                _program_name,
                                model_file_name,
                                ve.getLocalizedMessage(),
                                error=ve,
                                class_name=_class_name,
                                method_name=_method_name)
            ex = exception_helper.create_compare_exception(
                ve.getLocalizedMessage(), error=ve)
            self._logger.throwing(ex,
                                  class_name=_class_name,
                                  method_name=_method_name)
            return VALIDATION_FAIL