def generate_k8s_script(model_context, token_dictionary, model_dictionary):
    """
    Generate a shell script for creating k8s secrets.
    :param model_context: used to determine output directory
    :param token_dictionary: contains every token
    :param model_dictionary: used to determine domain UID
    """
    target_config = model_context.get_target_configuration()
    if not target_config.requires_secrets_script():
        return

    # determine the domain name and UID
    topology = dictionary_utils.get_dictionary_element(model_dictionary,
                                                       TOPOLOGY)
    domain_name = dictionary_utils.get_element(topology, NAME)
    if domain_name is None:
        domain_name = DEFAULT_WLS_DOMAIN_NAME

    domain_uid = k8s_helper.get_domain_uid(domain_name)

    nl = '\n'
    file_location = model_context.get_kubernetes_output_dir()
    k8s_file = os.path.join(file_location, "create_k8s_secrets.sh")
    k8s_script = open(k8s_file, 'w')

    k8s_script.write('#!/bin/bash' + nl)

    k8s_script.write(nl)
    k8s_script.write('set -eu' + nl)

    k8s_script.write(nl)
    message = exception_helper.get_message("WLSDPLY-01665", ADMIN_USER_TAG,
                                           ADMIN_PASSWORD_TAG)
    k8s_script.write("# " + message + nl)
    k8s_script.write('NAMESPACE=default' + nl)
    k8s_script.write('DOMAIN_UID=' + domain_uid + nl)

    k8s_script.write(nl)
    k8s_script.write('function create_k8s_secret {' + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE delete secret ${DOMAIN_UID}-$1 --ignore-not-found'
        + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE create secret generic ${DOMAIN_UID}-$1 --from-literal=password=$2'
        + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE label secret ${DOMAIN_UID}-$1 weblogic.domainUID=${DOMAIN_UID}'
        + nl)
    k8s_script.write('}' + nl)

    k8s_script.write(nl)
    k8s_script.write('function create_paired_k8s_secret {' + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE delete secret ${DOMAIN_UID}-$1 --ignore-not-found'
        + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE create secret generic ${DOMAIN_UID}-$1' +
        ' --from-literal=username=$2 --from-literal=password=$3' + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE label secret ${DOMAIN_UID}-$1 weblogic.domainUID=${DOMAIN_UID}'
        + nl)
    k8s_script.write('}' + nl)

    command_string = "create_paired_k8s_secret %s %s %s" \
                     % (WEBLOGIC_CREDENTIALS_SECRET_NAME, ADMIN_USER_TAG, ADMIN_PASSWORD_TAG)

    k8s_script.write(nl)
    message = exception_helper.get_message("WLSDPLY-01664", ADMIN_USER_TAG,
                                           ADMIN_PASSWORD_TAG,
                                           WEBLOGIC_CREDENTIALS_SECRET_NAME)
    k8s_script.write("# " + message + nl)
    k8s_script.write(command_string + nl)

    for property_name in token_dictionary:
        # AdminPassword, AdminUser are created separately,
        # and SecurityConfig.NodeManagerPasswordEncrypted is the short name which filters out
        if property_name in [
                'AdminPassword', 'AdminUserName',
                'SecurityConfig.NodeManagerPasswordEncrypted'
        ]:
            continue

        user_name = find_user_name(property_name, model_dictionary)
        secret_name = _create_secret_name(property_name)

        if user_name is None:
            message = exception_helper.get_message("WLSDPLY-01663",
                                                   PASSWORD_TAG, secret_name)
            command_string = "create_k8s_secret %s %s " \
                             % (secret_name, PASSWORD_TAG)
        else:
            message = exception_helper.get_message("WLSDPLY-01664", USER_TAG,
                                                   PASSWORD_TAG, secret_name)
            command_string = "create_paired_k8s_secret %s %s %s " \
                             % (secret_name, user_name, PASSWORD_TAG)

        k8s_script.write(nl)
        k8s_script.write("# " + message + nl)
        k8s_script.write(command_string + nl)

    k8s_script.close()
    FileUtils.chmod(k8s_file, 0750)
예제 #2
0
def _build_template_hash(model, model_context, aliases):
    """
    Create a dictionary of substitution values to apply to the templates.
    :param model: Model object used to derive values
    :param model_context: used to determine domain type
    :param aliases: used to derive folder names
    :return: the hash dictionary
    """
    template_hash = dict()

    # domain name and prefix

    domain_name = dictionary_utils.get_element(model.get_model_topology(),
                                               NAME)
    if domain_name is None:
        domain_name = DEFAULT_WLS_DOMAIN_NAME

    template_hash[DOMAIN_NAME] = domain_name

    # should change spaces to hyphens?
    template_hash[DOMAIN_PREFIX] = domain_name.lower()

    # domain UID

    domain_uid = k8s_helper.get_domain_uid(domain_name)
    template_hash[DOMAIN_UID] = domain_uid

    # admin credential

    admin_secret = domain_uid + target_configuration_helper.WEBLOGIC_CREDENTIALS_SECRET_SUFFIX
    template_hash[WEBLOGIC_CREDENTIALS_SECRET] = admin_secret

    # configuration / model
    template_hash[DOMAIN_TYPE] = model_context.get_domain_type()

    # clusters

    clusters = []
    cluster_list = dictionary_utils.get_dictionary_element(
        model.get_model_topology(), CLUSTER)
    for cluster_name in cluster_list:
        cluster_hash = dict()
        cluster_hash[CLUSTER_NAME] = cluster_name

        cluster_values = dictionary_utils.get_dictionary_element(
            cluster_list, cluster_name)
        server_count = k8s_helper.get_server_count(cluster_name,
                                                   cluster_values,
                                                   model.get_model())
        cluster_hash[REPLICAS] = str(server_count)
        clusters.append(cluster_hash)

    template_hash[CLUSTERS] = clusters
    template_hash[HAS_CLUSTERS] = len(clusters) != 0

    # databases

    databases = []

    location = LocationContext().append_location(JDBC_SYSTEM_RESOURCE)
    name_token = aliases.get_name_token(location)
    location.append_location(JDBC_RESOURCE, JDBC_DRIVER_PARAMS)

    system_resources = dictionary_utils.get_dictionary_element(
        model.get_model_resources(), JDBC_SYSTEM_RESOURCE)
    for jdbc_name in system_resources:
        database_hash = dict()
        database_hash[DATASOURCE_NAME] = jdbc_name

        named = dictionary_utils.get_dictionary_element(
            system_resources, jdbc_name)
        resources = dictionary_utils.get_dictionary_element(
            named, JDBC_RESOURCE)
        driver_params = dictionary_utils.get_dictionary_element(
            resources, JDBC_DRIVER_PARAMS)
        url = dictionary_utils.get_element(driver_params, URL)
        if url is None:
            url = ''
        database_hash[DS_URL] = url

        # should change spaces to hyphens?
        database_hash[DATABASE_PREFIX] = jdbc_name.lower()

        # get the name that matches secret
        location.add_name_token(name_token, jdbc_name)
        secret_name = target_configuration_helper.get_secret_name_for_location(
            location, domain_uid, aliases)
        database_hash[DATABASE_CREDENTIALS] = secret_name

        databases.append(database_hash)

    template_hash[DATABASES] = databases
    template_hash[HAS_DATABASES] = len(databases) != 0

    return template_hash
예제 #3
0
def generate_k8s_script(model_context, token_dictionary, model_dictionary, exception_type):
    """
    Generate a shell script for creating k8s secrets.
    :param model_context: used to determine output directory
    :param token_dictionary: contains every token
    :param model_dictionary: used to determine domain UID
    :param exception_type: type of exception to throw
    """

    # determine the domain name and UID
    topology = dictionary_utils.get_dictionary_element(model_dictionary, TOPOLOGY)
    domain_name = dictionary_utils.get_element(topology, NAME)
    if domain_name is None:
        domain_name = DEFAULT_WLS_DOMAIN_NAME

    domain_uid = k8s_helper.get_domain_uid(domain_name)
    comment = exception_helper.get_message("WLSDPLY-01665")
    script_hash = {'domainUid': domain_uid, 'topComment': comment}

    # build a map of secret names (jdbc-generic1) to keys (username, password)
    secret_map = {}
    for property_name in token_dictionary:
        halves = property_name.split(':', 1)
        value = token_dictionary[property_name]
        if len(halves) == 2:
            secret_name = halves[0]

            # admin credentials are inserted later, at the top of the list
            if secret_name == WEBLOGIC_CREDENTIALS_SECRET_NAME:
                continue

            secret_key = halves[1]
            if secret_name not in secret_map:
                secret_map[secret_name] = {}
            secret_keys = secret_map[secret_name]
            secret_keys[secret_key] = value

    # update the hash with secrets and paired secrets
    secrets = []
    paired_secrets = [_build_secret_hash(WEBLOGIC_CREDENTIALS_SECRET_NAME, USER_TAG, PASSWORD_TAG)]

    secret_names = secret_map.keys()
    secret_names.sort()
    for secret_name in secret_names:
        secret_keys = secret_map[secret_name]
        user_name = dictionary_utils.get_element(secret_keys, SECRET_USERNAME_KEY)
        if user_name is None:
            secrets.append(_build_secret_hash(secret_name, None, PASSWORD_TAG))
        else:
            paired_secrets.append(_build_secret_hash(secret_name, user_name, PASSWORD_TAG))

    script_hash['secrets'] = secrets
    script_hash['pairedSecrets'] = paired_secrets
    script_hash['longMessage'] = exception_helper.get_message('WLSDPLY-01667', '${LONG_SECRETS_COUNT}')

    long_messages = [
        {'text': exception_helper.get_message('WLSDPLY-01668')},
        {'text': exception_helper.get_message('WLSDPLY-01669')},
        {'text': exception_helper.get_message('WLSDPLY-01670')}
    ]
    script_hash['longMessageDetails'] = long_messages

    file_location = model_context.get_output_dir()
    k8s_file = File(file_location, K8S_SCRIPT_NAME)
    file_template_helper.create_file_from_resource(K8S_SCRIPT_RESOURCE_PATH, script_hash, k8s_file, exception_type)
    FileUtils.chmod(k8s_file.getPath(), 0750)
    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 a metadata section if not present, since we'll at least add name
        if METADATA not in resource_dict:
            _add_to_top(resource_dict, METADATA, PyOrderedDict())
        metadata_section = resource_dict[METADATA]

        # add kind if not present
        if KIND not in resource_dict:
            _add_to_top(resource_dict, KIND, DEFAULT_KIND)

        # add API version if not present
        if API_VERSION not in resource_dict:
            _add_to_top(resource_dict, API_VERSION, DEFAULT_API_VERSION)

        # 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
            domain_name = k8s_helper.get_domain_uid(domain_name)
            metadata_section[K_NAME] = domain_name
        domain_uid = metadata_section[K_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 = list()
            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 = list()
                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(),
                                                               self._aliases)
                    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)

        # create a configuration section in spec if needed
        if CONFIGURATION not in spec_section:
            spec_section[CONFIGURATION] = PyOrderedDict()
        configuration_section = spec_section[CONFIGURATION]

        # create a model section in configuration if needed
        if MODEL not in configuration_section:
            configuration_section[MODEL] = PyOrderedDict()
        model_section = configuration_section[MODEL]

        # set domainType if not specified
        if DOMAIN_TYPE not in model_section:
            model_section[DOMAIN_TYPE] = self._model_context.get_domain_type()

        if SECRETS in configuration_section:
            # if secrets specified, convert them to a hyphen list
            secrets = alias_utils.convert_to_model_type("list", configuration_section[SECRETS], MODEL_LIST_DELIMITER)
            secrets_list = list()
            secrets_list.extend(secrets)

        else:
            # pull the secrets from the model
            secrets_list = list()
            _add_secrets(self._model.get_model(), secrets_list, domain_uid)

        if secrets_list:
            configuration_section[SECRETS] = secrets_list

        return
예제 #5
0
def generate_k8s_script(model_context, token_dictionary, model_dictionary):
    """
    Generate a shell script for creating k8s secrets.
    :param model_context: used to determine output directory
    :param token_dictionary: contains every token
    :param model_dictionary: used to determine domain UID
    """

    # determine the domain name and UID
    topology = dictionary_utils.get_dictionary_element(model_dictionary,
                                                       TOPOLOGY)
    domain_name = dictionary_utils.get_element(topology, NAME)
    if domain_name is None:
        domain_name = DEFAULT_WLS_DOMAIN_NAME

    domain_uid = k8s_helper.get_domain_uid(domain_name)

    nl = '\n'
    file_location = model_context.get_kubernetes_output_dir()
    k8s_file = os.path.join(file_location, "create_k8s_secrets.sh")
    k8s_script = open(k8s_file, 'w')

    k8s_script.write('#!/bin/bash' + nl)

    k8s_script.write(nl)
    k8s_script.write('set -eu' + nl)

    k8s_script.write(nl)
    message = exception_helper.get_message("WLSDPLY-01665", ADMIN_USER_TAG,
                                           ADMIN_PASSWORD_TAG)
    k8s_script.write("# " + message + nl)
    k8s_script.write('NAMESPACE=default' + nl)
    k8s_script.write('DOMAIN_UID=' + domain_uid + nl)

    k8s_script.write(nl)
    k8s_script.write('function create_k8s_secret {' + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE delete secret ${DOMAIN_UID}-$1 --ignore-not-found'
        + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE create secret generic ${DOMAIN_UID}-$1 --from-literal=password=$2'
        + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE label secret ${DOMAIN_UID}-$1 weblogic.domainUID=${DOMAIN_UID}'
        + nl)
    k8s_script.write('}' + nl)

    k8s_script.write(nl)
    k8s_script.write('function create_paired_k8s_secret {' + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE delete secret ${DOMAIN_UID}-$1 --ignore-not-found'
        + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE create secret generic ${DOMAIN_UID}-$1' +
        ' --from-literal=username=$2 --from-literal=password=$3' + nl)
    k8s_script.write(
        '  kubectl -n $NAMESPACE label secret ${DOMAIN_UID}-$1 weblogic.domainUID=${DOMAIN_UID}'
        + nl)
    k8s_script.write('}' + nl)

    command_string = "create_paired_k8s_secret %s %s %s" \
                     % (WEBLOGIC_CREDENTIALS_SECRET_NAME, ADMIN_USER_TAG, ADMIN_PASSWORD_TAG)

    k8s_script.write(nl)
    message = exception_helper.get_message("WLSDPLY-01664", ADMIN_USER_TAG,
                                           ADMIN_PASSWORD_TAG,
                                           WEBLOGIC_CREDENTIALS_SECRET_NAME)
    k8s_script.write("# " + message + nl)
    k8s_script.write(command_string + nl)

    # build a map of secret names (jdbc-generic1) to keys (username, password)
    secret_map = {}
    for property_name in token_dictionary:
        halves = property_name.split(':', 1)
        value = token_dictionary[property_name]
        if len(halves) == 2:
            secret_name = halves[0]

            # admin credentials are hard-coded in the script, to be first in the list
            if secret_name == WEBLOGIC_CREDENTIALS_SECRET_NAME:
                continue

            secret_key = halves[1]
            if secret_name not in secret_map:
                secret_map[secret_name] = {}
            secret_keys = secret_map[secret_name]
            secret_keys[secret_key] = value

    secret_names = secret_map.keys()
    secret_names.sort()

    for secret_name in secret_names:
        secret_keys = secret_map[secret_name]
        user_name = dictionary_utils.get_element(secret_keys,
                                                 SECRET_USERNAME_KEY)

        if user_name is None:
            message = exception_helper.get_message("WLSDPLY-01663",
                                                   PASSWORD_TAG, secret_name)
            command_string = "create_k8s_secret %s %s " \
                             % (secret_name, PASSWORD_TAG)
        else:
            message = exception_helper.get_message("WLSDPLY-01664", USER_TAG,
                                                   PASSWORD_TAG, secret_name)
            command_string = "create_paired_k8s_secret %s %s %s " \
                             % (secret_name, user_name, PASSWORD_TAG)

        k8s_script.write(nl)
        k8s_script.write("# " + message + nl)
        k8s_script.write(command_string + nl)

    k8s_script.close()
    FileUtils.chmod(k8s_file, 0750)
예제 #6
0
def _build_template_hash(model, model_context, aliases, credential_injector):
    """
    Create a dictionary of substitution values to apply to the templates.
    :param model: Model object used to derive values
    :param model_context: used to determine domain type
    :param aliases: used to derive folder names
    :param credential_injector: used to identify secrets
    :return: the hash dictionary
    """
    template_hash = dict()

    # actual domain name

    domain_name = dictionary_utils.get_element(model.get_model_topology(),
                                               NAME)
    if domain_name is None:
        domain_name = DEFAULT_WLS_DOMAIN_NAME

    # domain UID, name and prefix must follow DNS-1123

    domain_uid = k8s_helper.get_domain_uid(domain_name)
    template_hash[DOMAIN_UID] = domain_uid
    template_hash[DOMAIN_NAME] = domain_uid
    template_hash[DOMAIN_PREFIX] = domain_uid

    # secrets that should not be included in secrets section
    declared_secrets = []

    # admin credential

    admin_secret = domain_uid + target_configuration_helper.WEBLOGIC_CREDENTIALS_SECRET_SUFFIX
    declared_secrets.append(admin_secret)
    template_hash[WEBLOGIC_CREDENTIALS_SECRET] = admin_secret

    # configuration / model
    template_hash[DOMAIN_TYPE] = model_context.get_domain_type()

    # clusters

    clusters = []
    cluster_list = dictionary_utils.get_dictionary_element(
        model.get_model_topology(), CLUSTER)
    for cluster_name in cluster_list:
        cluster_hash = dict()
        cluster_hash[CLUSTER_NAME] = cluster_name

        cluster_values = dictionary_utils.get_dictionary_element(
            cluster_list, cluster_name)
        server_count = k8s_helper.get_server_count(cluster_name,
                                                   cluster_values,
                                                   model.get_model(), aliases)
        cluster_hash[REPLICAS] = str(server_count)
        clusters.append(cluster_hash)

    template_hash[CLUSTERS] = clusters
    template_hash[HAS_CLUSTERS] = len(clusters) != 0

    # databases

    databases = []

    location = LocationContext().append_location(JDBC_SYSTEM_RESOURCE)
    name_token = aliases.get_name_token(location)
    location.append_location(JDBC_RESOURCE, JDBC_DRIVER_PARAMS)

    system_resources = dictionary_utils.get_dictionary_element(
        model.get_model_resources(), JDBC_SYSTEM_RESOURCE)
    for jdbc_name in system_resources:
        database_hash = dict()
        database_hash[DATASOURCE_NAME] = jdbc_name

        named = dictionary_utils.get_dictionary_element(
            system_resources, jdbc_name)
        resources = dictionary_utils.get_dictionary_element(
            named, JDBC_RESOURCE)
        driver_params = dictionary_utils.get_dictionary_element(
            resources, JDBC_DRIVER_PARAMS)
        url = dictionary_utils.get_element(driver_params, URL)
        if url is None:
            url = ''
        database_hash[DS_URL] = url

        # should change spaces to hyphens?
        database_hash[DATABASE_PREFIX] = jdbc_name.lower()

        # get the name that matches secret
        location.add_name_token(name_token, jdbc_name)
        secret_name = target_configuration_helper.get_secret_name_for_location(
            location, domain_uid, aliases)
        database_hash[DATABASE_CREDENTIALS] = secret_name

        databases.append(database_hash)

    template_hash[DATABASES] = databases
    template_hash[HAS_DATABASES] = len(databases) != 0

    # additional secrets - exclude admin

    additional_secrets = []

    # combine user/password properties to get a single list
    secrets = []
    for property_name in credential_injector.get_variable_cache():
        halves = property_name.split(':', 1)
        name = halves[0]
        if name not in secrets:
            secrets.append(name)

    for secret in secrets:
        secrets_hash = dict()
        qualified_name = domain_uid + "-" + secret
        if qualified_name not in declared_secrets:
            secrets_hash[ADDITIONAL_SECRET_NAME] = qualified_name
            additional_secrets.append(secrets_hash)

    template_hash[ADDITIONAL_SECRETS] = additional_secrets
    template_hash[HAS_ADDITIONAL_SECRETS] = len(additional_secrets) != 0

    return template_hash
예제 #7
0
 def _check_uid(self, domain_name, expected_uid):
     domain_uid = k8s_helper.get_domain_uid(domain_name)
     self.assertEquals(expected_uid, domain_uid, "Domain UID for " + domain_name + " should be " + expected_uid)