Esempio n. 1
0
    def _is_alias_folder(self, path):
        """
        Check if the delimited path is a folder or attribute
        :param path: '|' delimited path
        :return: true if it is a folder otherwise false
        """
        debug("DEBUG: Entering is_alias_folder %s", path)
        path_tokens = path.split(PATH_TOKEN)
        model_context = ModelContext("test", {})
        aliases = Aliases(model_context=model_context,
                          wlst_mode=WlstModes.OFFLINE)
        location = LocationContext()
        last_token = path_tokens[-1]
        alias_helper = AliasHelper(aliases, __logger, ExceptionType.COMPARE)

        found = True
        name_token_next = False
        for path_token in path_tokens[1:]:
            if name_token_next:
                token_name = aliases.get_name_token(location)
                location.add_name_token(token_name, path_token)
                name_token_next = False
            else:
                location.append_location(path_token)
                if last_token == path_token:
                    break
                name_token_next = alias_helper.supports_multiple_mbean_instances(
                    location)
            attrib_names = alias_helper.get_model_attribute_names(location)
            if last_token in attrib_names:
                found = False

        debug("DEBUG: is_alias_folder %s %s", path, found)

        return found
Esempio n. 2
0
class DomainResourceExtractor:
    """
    Create a domain resource file for use with Kubernetes deployment.
    """
    _class_name = "DomainResourceExtractor"

    # the name field keys corresponding to named model elements
    NAME_KEY_MAP = {CHANNELS: 'channelName', CLUSTERS: CLUSTER_NAME}

    def __init__(self, model, model_context, aliases, logger):
        self._model = model
        self._model_context = model_context
        self._aliases = AliasHelper(aliases, logger, ExceptionType.DEPLOY)
        self._logger = logger
        return

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

        resource_file = self._model_context.get_domain_resource_file()
        self._logger.info("WLSDPLY-10000",
                          resource_file,
                          method_name=_method_name,
                          class_name=self._class_name)

        # create the target file directory, if needed
        resource_dir = File(resource_file).getParentFile()
        if (not resource_dir.isDirectory()) and (not resource_dir.mkdirs()):
            mkdir_ex = exception_helper.create_deploy_exception(
                'WLSDPLY-10001', resource_dir)
            raise mkdir_ex

        # build the resource file structure from the kubernetes section of the model
        resource_dict = self._create_domain_resource_dictionary()

        # revise the resource file structure with values from command line, and elsewhere in model
        self._update_resource_dictionary(resource_dict)

        # write the resource file structure to the output file
        writer = PythonToFile(resource_dict)

        writer.write_to_file(resource_file)
        return

    def _create_domain_resource_dictionary(self):
        """
        Build the resource file structure from the kubernetes section of the model.
        :return: the resource file structure
        """
        kubernetes_map = self._model.get_model_kubernetes()

        resource_dict = PyOrderedDict()

        attribute_location = self._aliases.get_model_section_attribute_location(
            KUBERNETES)
        top_attributes_map = self._aliases.get_model_attribute_names_and_types(
            attribute_location)
        top_folders = self._aliases.get_model_section_top_level_folder_names(
            KUBERNETES)

        self._process_fields(kubernetes_map, top_folders, top_attributes_map,
                             LocationContext(), resource_dict)
        return resource_dict

    def _process_fields(self, model_dict, folder_names, attributes_map,
                        location, target_dict):
        """
        Transfer folders and attributes from the model dictionary to the target domain resource dictionary.
        For the top level, the folders and attributes are not derived directly from the location.
        :param model_dict: the source model dictionary
        :param folder_names: the names of the folders at this location
        :param attributes_map: the map of attribute names to types for this location
        :param location: the location used for alias processing
        :param target_dict: the target dictionary for the domain resource file.
       """
        for key, model_value in model_dict.items():
            if key in attributes_map.keys():
                type_name = attributes_map[key]
                target_dict[key] = _get_target_value(model_value, type_name)

            elif key in folder_names:
                child_location = LocationContext(location).append_location(key)

                if self._aliases.supports_multiple_mbean_instances(
                        child_location):
                    target_dict[key] = self._build_dictionary_list(
                        key, model_value, child_location)
                else:
                    if key not in target_dict:
                        target_dict[key] = PyOrderedDict()
                    target_child_dict = target_dict[key]
                    self._process_location_fields(model_value, child_location,
                                                  target_child_dict)
        return

    def _process_location_fields(self, model_dict, location, target_dict):
        """
        Transfer folders and attributes from the model dictionary to the target domain resource dictionary.
        Below the top level, the folders and attributes can be derived from the location.
        :param model_dict: the source model dictionary
        :param location: the location used for alias processing
        :param target_dict: the target dictionary for the domain resource file.
       """
        attributes_map = self._aliases.get_model_attribute_names_and_types(
            location)
        folder_names = self._aliases.get_model_subfolder_names(location)
        self._process_fields(model_dict, folder_names, attributes_map,
                             location, target_dict)
        return

    def _build_dictionary_list(self, model_key, name_dictionary, location):
        """
        Build a dictionary list object based on the name dictionary and location.
        :param name_dictionary: a dictionary containing named levels
        :param location: the location used for alias resolution
        :return:
        """
        child_list = DictionaryList()
        for name in name_dictionary:
            model_named_dict = name_dictionary[name]
            name_key = self._get_name_key(model_key)
            target_list_dict = PyOrderedDict()
            target_list_dict[name_key] = name
            self._process_location_fields(model_named_dict, location,
                                          target_list_dict)
            child_list.append(target_list_dict)
        return child_list

    def _get_name_key(self, key):
        """
        Return the key to be used for the name in a dictionary list element.
        :param key: the folder key in the model
        :return: the name key
        """
        key = dictionary_utils.get_element(self.NAME_KEY_MAP, key)
        if key is not None:
            return key
        return 'name'

    def _update_resource_dictionary(self, resource_dict):
        """
        Revise the resource file structure with values from defaults, command line, and elsewhere in model
        :param resource_dict: the resource file dictionary
        """
        _method_name = '_update_resource_dictionary'

        # add API version if not present
        if API_VERSION not in resource_dict:
            resource_dict[API_VERSION] = DEFAULT_API_VERSION

        # add kind if not present
        if KIND not in resource_dict:
            resource_dict[KIND] = DEFAULT_KIND

        # add a metadata section if not present, since we'll at least add name
        if METADATA not in resource_dict:
            resource_dict[METADATA] = PyOrderedDict()
        metadata_section = resource_dict[METADATA]

        # if metadata name not present, use the domain name from the model, or default
        if K_NAME not in metadata_section:
            domain_name = dictionary_utils.get_element(
                self._model.get_model_topology(), NAME)
            if domain_name is None:
                domain_name = DEFAULT_WLS_DOMAIN_NAME
            metadata_section[K_NAME] = domain_name

        # add a spec section if not present, since we'll at least add domain home
        if SPEC not in resource_dict:
            resource_dict[SPEC] = PyOrderedDict()
        spec_section = resource_dict[SPEC]

        # only set domain home if it is not present in spec section
        if DOMAIN_HOME not in spec_section:
            spec_section[DOMAIN_HOME] = self._model_context.get_domain_home()

        # only set image if it is not present in spec section
        if IMAGE not in spec_section:
            spec_section[IMAGE] = DEFAULT_IMAGE

        # imagePullSecrets is required unless imagePullPolicy is Never
        pull_secrets_required = True
        if IMAGE_PULL_POLICY in spec_section:
            policy = str(spec_section[IMAGE_PULL_POLICY])
            pull_secrets_required = (policy != NEVER)

        # if imagePullSecrets required and not present, add a list with one FIX ME value
        if pull_secrets_required and (IMAGE_PULL_SECRETS not in spec_section):
            secrets_list = DictionaryList()
            secrets_list.append({'name': DEFAULT_IMAGE_PULL_SECRETS})
            spec_section[IMAGE_PULL_SECRETS] = secrets_list

        # if webLogicCredentialsSecret not present, add it using the FIX ME value
        if WEBLOGIC_CREDENTIALS_SECRET not in spec_section:
            spec_section[
                WEBLOGIC_CREDENTIALS_SECRET] = DEFAULT_WEBLOGIC_CREDENTIALS_SECRET

        # only update clusters if section is not present in spec section
        if CLUSTERS not in spec_section:
            topology = self._model.get_model_topology()
            model_clusters = dictionary_utils.get_dictionary_element(
                topology, CLUSTER)
            if len(model_clusters) > 0:
                cluster_list = DictionaryList()
                spec_section[CLUSTERS] = cluster_list
                for cluster_name, cluster_values in model_clusters.items():
                    server_count = k8s_helper.get_server_count(
                        cluster_name, cluster_values, self._model.get_model())
                    cluster_dict = PyOrderedDict()
                    cluster_dict[CLUSTER_NAME] = cluster_name
                    cluster_dict[REPLICAS] = server_count

                    self._logger.info("WLSDPLY-10002",
                                      cluster_name,
                                      server_count,
                                      method_name=_method_name,
                                      class_name=self._class_name)
                    cluster_list.append(cluster_dict)
        return
class Deployer(object):
    """
    The base class for deployers.
    Maintains model, model context, WLST mode, etc.
    Has common methods for deployers.
    """
    _class_name = "Deployer"

    _mbean_interface = Class.forName('weblogic.management.configuration.ConfigurationMBean')
    _object_name_class = Class.forName('javax.management.ObjectName')
    _list_interface = Class.forName('java.util.List')

    def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE):
        self.name = self._class_name
        self.model = model
        self.wlst_mode = wlst_mode
        self.model_context = model_context
        self.aliases = aliases
        self.logger = PlatformLogger('wlsdeploy.deploy')
        self.alias_helper = AliasHelper(aliases, self.logger, ExceptionType.DEPLOY)
        self.wls_helper = WebLogicHelper(self.logger)
        self.wlst_helper = WlstHelper(self.logger, ExceptionType.DEPLOY)
        self.attribute_setter = AttributeSetter(self.aliases, self.logger, ExceptionType.DEPLOY, wlst_mode=wlst_mode)

        self.archive_helper = None
        archive_file_name = self.model_context.get_archive_file_name()
        if archive_file_name is not None:
            self.archive_helper = ArchiveHelper(archive_file_name, self.model_context.get_domain_home(), self.logger,
                                                exception_helper.ExceptionType.DEPLOY)
        return

    def _add_named_elements(self, type_name, model_nodes, location):
        """
        Add each named element from the specified nodes in WLST and set its attributes.
        Sub-folders are processed in a generic manner if present.
        It is assumed that there are no attributes or sub-folders with special processing.
        :param type_name: the type name of the child nodes
        :param model_nodes: the child nodes of a model element
        :param location: the location where elements should be added
        """
        _method_name = '_add_named_elements'

        if len(model_nodes) == 0:
            return

        parent_type, parent_name = self.get_location_type_and_name(location)
        location = LocationContext(location).append_location(type_name)
        if not self._check_location(location):
            return

        deployer_utils.check_flattened_folder(location, self.alias_helper)
        existing_names = deployer_utils.get_existing_object_list(location, self.alias_helper)

        token = self.alias_helper.get_name_token(location)
        for name in model_nodes:
            is_add = name not in existing_names
            log_helper.log_updating_named_folder(type_name, name, parent_type, parent_name, is_add, self._class_name,
                                                 _method_name)

            if token is not None:
                location.add_name_token(token, name)
            deployer_utils.create_and_cd(location, existing_names, self.alias_helper)

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

    def _add_subfolders(self, model_nodes, location, excludes=None):
        """
        Add each model sub-folder from the specified nodes and set its attributes.
        :param model_nodes: the child nodes of a model element
        :param location: the location where sub-folders should be added
        :param excludes: optional list of sub-folder names to be excluded from processing
        """
        location = LocationContext(location)
        model_subfolder_names = self.alias_helper.get_model_subfolder_names(location)

        for subfolder in model_nodes:
            key_excluded = (excludes is not None) and (subfolder in excludes)
            if subfolder in model_subfolder_names and not key_excluded:
                subfolder_nodes = model_nodes[subfolder]
                if len(subfolder_nodes) != 0:
                    sub_location = LocationContext(location).append_location(subfolder)
                    if self.alias_helper.supports_multiple_mbean_instances(sub_location):
                        self._add_named_elements(subfolder, subfolder_nodes, location)
                    else:
                        self._add_model_elements(subfolder, subfolder_nodes, location)
        return

    def _add_model_elements(self, type_name, model_nodes, location):
        """
        Add each model element from the specified nodes at the specified location and set its attributes.
        :param model_nodes: the child nodes of a model element
        :param location: the location where sub-folders should be added
        :param type_name: the name of the model folder to add
        """
        _method_name = '_add_model_elements'

        parent_type, parent_name = self.get_location_type_and_name(location)
        location = LocationContext(location).append_location(type_name)
        if not self._check_location(location):
            return

        deployer_utils.check_flattened_folder(location, self.alias_helper)
        existing_subfolder_names = deployer_utils.get_existing_object_list(location, self.alias_helper)

        mbean_name = deployer_utils.get_mbean_name(location, existing_subfolder_names, self.alias_helper)
        is_add = mbean_name not in existing_subfolder_names
        log_helper.log_updating_folder(type_name, parent_type, parent_name, is_add, self._class_name, _method_name)

        deployer_utils.create_and_cd(location, existing_subfolder_names, self.alias_helper)

        self._set_attributes_and_add_subfolders(location, model_nodes)
        return

    def _set_attributes_and_add_subfolders(self, location, model_nodes):
        """
        Set the attributes and add sub-folders for the specified location.
        This method can be overridden for finer control of the ordering
        :param location: the location of the attributes and sub-folders
        :param model_nodes: a map of model nodes including attributes and sub-folders
        :raise: DeployException: if an error condition is encountered
        """
        self.set_attributes(location, model_nodes)
        self._add_subfolders(model_nodes, location)
        return

    def set_attributes(self, location, model_nodes, excludes=None):
        """
        Set all the attributes in the model_nodes list. Exclude items that are sub-folders.
        :param location: the location of the attributes to be set
        :param model_nodes: a map of model nodes with attributes to be set
        :param excludes: a list of items that should not be set
        :raise: DeployException: if an error condition is encountered
        """
        _method_name = 'set_attributes'
        attribute_names = self.alias_helper.get_model_attribute_names(location)
        uses_path_tokens_attribute_names = self.alias_helper.get_model_uses_path_tokens_attribute_names(location)
        restart_attribute_names = self.alias_helper.get_model_restart_required_attribute_names(location)
        merge_attribute_names = self.alias_helper.get_model_merge_required_attribute_names(location)
        lsa_required_attribute_names = self.aliases.get_model_lsa_required_attribute_names(location)
        set_method_map = self.alias_helper.get_model_mbean_set_method_attribute_names_and_types(location)

        for key in model_nodes:
            key_excluded = (excludes is not None) and (key in excludes)
            if key in attribute_names and not key_excluded:
                value = model_nodes[key]
                if key in uses_path_tokens_attribute_names:
                    self._extract_from_archive_if_needed(location, key, value)

                wlst_merge_value = None
                if key in merge_attribute_names:
                    wlst_merge_value = self._get_existing_wlst_value(location, key, lsa_required_attribute_names)

                if not self._skip_setting_attribute(key, value, wlst_merge_value, restart_attribute_names) and \
                        (not self.set_special_attribute(location, key, value, wlst_merge_value, set_method_map)):
                    try:
                        self.attribute_setter.set_attribute(location, key, value, wlst_merge_value)
                    except PyWLSTException, pwe:
                        loc_type, loc_name = self.get_location_type_and_name(location)
                        ex = exception_helper.create_deploy_exception('WLSDPLY-09200', key, loc_type, loc_name,
                                                                      pwe.getLocalizedMessage(), error=pwe)
                        self.logger.throwing(ex, class_name=self._class_name, method_name=_method_name)
                        raise ex
        return
Esempio n. 4
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:
Esempio n. 5
0
class ModelHelpPrinter(object):
    """
    Class for printing the recognized model metadata to STDOUT.
    """
    def __init__(self, aliases, logger):
        """
        :param aliases: A reference to an Aliases class instance
        :param logger: A reference to the platform logger to write to, if a log entry needs to be made
        """
        self._logger = logger
        self._alias_helper = AliasHelper(aliases, self._logger,
                                         ExceptionType.CLA)

    def print_model_help(self, model_path, control_option, as_sample=False):
        """
        Prints out the help information for a given '''model_path'''. '''model_path''' needs to be specified
        using the following pattern:

                <model_section>[:/<section_folder>[/<section_subfolder>|...]]

        Examples:
                'domainInfo', 'domainInfo:' or 'domainInfo:/' (all 3 are equivalent)
                'topology:/Server'
                'resources:/JDBCSystemResource/JdbcResource/JDBCDriverParams'
                'appDeployments:/Application'

        :param model_path: a formatted string containing the model path
        :param control_option: a command-line switch that controls what is output
        :param as_sample: specifies that a model sample should be output
        :raises CLAException: if a problem is encountered
        """

        # print filter information, if not NORMAL
        if control_option == ControlOptions.RECURSIVE:
            print
            print _format_message('WLSDPLY-10102')
        elif control_option == ControlOptions.FOLDERS_ONLY:
            print
            print _format_message('WLSDPLY-10103')
        elif control_option == ControlOptions.ATTRIBUTES_ONLY:
            print
            print _format_message('WLSDPLY-10104')

        model_path_tokens = self._parse_model_path(model_path)

        section_name = model_path_tokens[0]
        valid_section_folder_keys = self._alias_helper.get_model_section_top_level_folder_names(
            section_name)

        if as_sample:
            sample_printer = ModelSamplePrinter(self._alias_helper,
                                                self._logger)
            sample_printer.print_model_sample(model_path_tokens,
                                              control_option)
        else:
            if model_path_tokens[0] == 'top':
                self._print_model_top_level_help()
            elif len(model_path_tokens) == 1:
                self._print_model_section_help(section_name,
                                               valid_section_folder_keys,
                                               control_option)
            else:
                self._print_model_folder_help(model_path_tokens,
                                              valid_section_folder_keys,
                                              control_option)

    def _parse_model_path(self, model_path):
        """
        Parse the specified model_path into a Python list of elements.
        The first element will be the section name.
        If not specified, the section name will be derived from the first path element.
        :param model_path: a string contain the model path to parse
        :return: a python list containing the section name, then each folder element
        :raises: CLAException if the path cannot be parsed, or the section name is invalid
        """
        _method_name = '_parse_model_path'

        self._logger.entering(model_path,
                              class_name=_class_name,
                              method_name=_method_name)

        match = MODEL_PATH_PATTERN.match(model_path)
        if match is None:
            ex = exception_helper.create_cla_exception('WLSDPLY-10108',
                                                       model_path)
            self._logger.throwing(ex,
                                  class_name=_class_name,
                                  method_name=_method_name)
            raise ex

        self._logger.finest('match.group(1)={0}, match.group(2)={1}',
                            str(match.group(1)),
                            str(match.group(2)),
                            class_name=_class_name,
                            method_name=_method_name)

        section = match.group(1)
        path = match.group(2)

        folders = []
        if path is not None:
            for folder in path.split('/'):
                # trailing or duplicate slashes may cause empty folder name
                if len(folder) > 0:
                    folders.append(folder)

        if section is None:
            section = self._get_section_for_folder_list(folders)

        section = section.replace(':', '')

        top_level_keys = model.get_model_top_level_keys()

        # 'top' is a special case for listing the sections
        all_section_keys = ['top']
        all_section_keys.extend(top_level_keys)

        if section not in all_section_keys:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-10109', section, str(', '.join(top_level_keys)))
            self._logger.throwing(ex,
                                  class_name=_class_name,
                                  method_name=_method_name)
            raise ex

        model_path_tokens = [section]
        model_path_tokens.extend(folders)
        return model_path_tokens

    def _get_section_for_folder_list(self, folder_list):
        """
        Derive the section name from the first folder in the specified list.
        :param folder_list: the list of folders in the model path
        :return: the section name
        :raises: CLAException if the section name cannot be determined
        """
        _method_name = '_get_section_for_folder_list'
        top_folder = folder_list[0]

        for section in KNOWN_TOPLEVEL_MODEL_SECTIONS:
            folder_keys = self._alias_helper.get_model_section_top_level_folder_names(
                section)
            if top_folder in folder_keys:
                return section

        ex = exception_helper.create_cla_exception('WLSDPLY-10101', top_folder)
        self._logger.throwing(ex,
                              class_name=_class_name,
                              method_name=_method_name)
        raise ex

    def _print_model_top_level_help(self):
        """
        Prints out all the valid section names for a model.
        The -recursive flag is disregarded for this case.
        """
        _method_name = '_print_model_top_level_help'
        self._logger.finest('sections={0}',
                            KNOWN_TOPLEVEL_MODEL_SECTIONS,
                            class_name=_class_name,
                            method_name=_method_name)

        title = _format_message('WLSDPLY-10113')

        # Print 'All Sections:' header
        print
        _print_indent(title, 0)
        print

        for section in KNOWN_TOPLEVEL_MODEL_SECTIONS:
            _print_indent(section, 1)

    def _print_model_section_help(self, section_name,
                                  valid_section_folder_keys, control_option):
        """
        Prints the help for a section of a model, when just the section_name[:] is provided
        :param section_name: the name of the model section
        :param valid_section_folder_keys: list of the valid top folders in the specified section
        :param control_option: A command-line switch that controls what is output to STDOUT
        """
        _method_name = '_print_model_section_help'

        self._logger.finest('1 section_name={0}',
                            section_name,
                            class_name=_class_name,
                            method_name=_method_name)

        location_path = '%s:' % section_name
        self._logger.finest('1 location_path={0}',
                            location_path,
                            class_name=_class_name,
                            method_name=_method_name)

        model_section = _format_message('WLSDPLY-10106', location_path)

        # Print 'Section: <model_section>' label and field
        print
        _print_indent(model_section, 0)

        if model_help_utils.show_attributes(control_option):
            attributes_location = self._alias_helper.get_model_section_attribute_location(
                section_name)
            if attributes_location is not None:
                self._print_attributes_help(attributes_location, 1)

        if model_help_utils.show_folders(control_option):
            print
            _print_indent(_format_message('WLSDPLY-10107'), 1)
            valid_section_folder_keys.sort()

            for section_folder_key in valid_section_folder_keys:
                _print_indent(section_folder_key, 2)

                if control_option == ControlOptions.RECURSIVE:
                    model_location = LocationContext().append_location(
                        section_folder_key)
                    self._print_subfolders_help(model_location, control_option,
                                                2)

    def _print_model_folder_help(self, model_path_tokens,
                                 valid_section_folder_keys, control_option):
        """
        Prints the help for a folder in a model, when more than just the section_name[:] is provided.
        The section name in the first token was already validated.
        :param model_path_tokens: a Python list of path elements built from model path
        :param valid_section_folder_keys: A list of valid folder names for the model section in the path
        :param control_option: A command-line switch that controls what is output to STDOUT
        """
        _method_name = '_print_model_folder_help'

        self._logger.finest(
            '1 model_path_tokens={0}, control_option={1}, valid_section_folder_keys={0}',
            str(model_path_tokens),
            ControlOptions.from_value(control_option),
            str(valid_section_folder_keys),
            class_name=_class_name,
            method_name=_method_name)

        section_name = model_path_tokens[0]
        top_folder = model_path_tokens[1]
        if top_folder not in valid_section_folder_keys:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-10110', section_name + ':', top_folder,
                ', '.join(valid_section_folder_keys))
            self._logger.throwing(ex,
                                  class_name=_class_name,
                                  method_name=_method_name)
            raise ex

        # Populate the location context using model_path_tokens[1:]
        model_location = LocationContext()
        for folder_key in model_path_tokens[1:]:
            model_location.append_location(folder_key)
            name_token = self._alias_helper.get_name_token(model_location)
            if name_token is not None:
                model_location.add_name_token(name_token, '%s-0' % folder_key)

            self._logger.finest('2 model_location={0}',
                                model_location,
                                class_name=_class_name,
                                method_name=_method_name)

        folder_path = '/'.join(model_path_tokens[1:])
        model_path = _format_message('WLSDPLY-10105',
                                     '%s:/%s' % (section_name, folder_path))
        type_name = self._get_folder_type_name(model_location)
        if type_name is not None:
            model_path += " (" + type_name + ")"

        # Print 'Path: <model_section>' header
        print
        _print_indent(model_path, 0)

        if model_help_utils.show_attributes(control_option):
            # Print the attributes associated with location context
            self._print_attributes_help(model_location, 1)

        if model_help_utils.show_folders(control_option):
            # Print the folders associated with location context
            print
            _print_indent(_format_message('WLSDPLY-10107'), 1)
            self._print_subfolders_help(model_location, control_option, 1)

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

    def _print_subfolders_help(self, model_location, control_option,
                               indent_level):
        """
        Prints the help for the folders in a model location, without header or leading space.
        :param model_location: the model location being worked on
        :param control_option: a command-line switch that controls what is output to STDOUT
        :param indent_level: the level to indent by, before printing output
        """
        _method_name = '_print_subfolders_help'

        valid_subfolder_keys = self._alias_helper.get_model_subfolder_names(
            model_location)
        self._logger.finest(
            '3 aliases.get_model_subfolder_names(model_location) returned: {0}',
            str(valid_subfolder_keys),
            class_name=_class_name,
            method_name=_method_name)

        if not valid_subfolder_keys:
            return

        valid_subfolder_keys.sort()

        for key in valid_subfolder_keys:
            model_location.append_location(key)
            name_token = self._alias_helper.get_name_token(model_location)
            if name_token is not None:
                model_location.add_name_token(name_token, '%s-0' % key)

            self._logger.finest('3 model_location={0}',
                                model_location,
                                class_name=_class_name,
                                method_name=_method_name)

            text = key
            type_name = self._get_folder_type_name(model_location)
            if type_name is not None:
                text += " (" + type_name + ")"

            _print_indent(text, indent_level + 1)

            if control_option == ControlOptions.RECURSIVE:
                # Call this method recursively
                self._print_subfolders_help(model_location, control_option,
                                            indent_level + 1)

            model_location.pop_location()

    def _print_attributes_help(self, model_location, indent_level):
        """
        Prints out the help for the attributes in a model location
        :param model_location: An object containing data about the model location being worked on
        :param indent_level: The level to indent by, before printing output
        """
        _method_name = '_print_attributes_help'

        attr_infos = self._alias_helper.get_model_attribute_names_and_types(
            model_location)
        self._logger.finer('WLSDPLY-05012',
                           str(model_location),
                           str(attr_infos),
                           class_name=_class_name,
                           method_name=_method_name)

        # Print 'Valid Attributes:' area label
        print
        _print_indent(_format_message('WLSDPLY-10111'), indent_level)

        if attr_infos:
            maxlen = 0
            for key in attr_infos:
                if len(key) > maxlen:
                    maxlen = len(key)
            formatted_string = '%-' + str(maxlen) + 's\t%s'

            attr_list = attr_infos.keys()
            attr_list.sort()
            for attr_name in attr_list:
                msg = formatted_string % (attr_name, attr_infos[attr_name])
                _print_indent(msg, indent_level + 1)

    def _get_folder_type_name(self, location):
        """
        Return text indicating the type of a folder, such as "multiple".
        :param location: the location to be checked
        :return: name of the folder type to be displayed, or None
        """
        if self._alias_helper.is_artificial_type_folder(location):
            return None
        if self._alias_helper.supports_multiple_mbean_instances(location):
            return "multiple"
        return None
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
Esempio n. 7
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