Пример #1
0
    def __init__(self, ctx, hname, user):

        self._userFull = f'{user.name}@{hname}'
        self._authKeys = None

        # Prepare command execution

        self._cmdShell = CmdShell()
        self._cmdSsh = CmdSsh(ctx, hname, user)
        self._rsyncSsh, self._rsyncSshSecrets = self._cmdSsh.getSshCmdAndSecrets(
            withLogin=False)

        # Get the path to the remote authorized_keys file

        homeDir = getHomeDir(ctx, hname, user)

        if not homeDir:
            fail(
                f"Could not determine the home directory of '{self._userFull}'"
            )

        self._akPath = f'{homeDir}/.ssh/authorized_keys'

        # Read the authorized_keys file

        info = _PublicKeyInformation(hname, user, self._akPath)

        self._read(info)  # Sets self._authKeys

        logging.debug(
            f'self._authKeys >>>\n{self._authKeys}\n<<< self._authKeys')
Пример #2
0
def getValidNfsServerAddress(ctx):
    """ Get valid NFS server address serving the OCP cluster net """

    # Get all IP addresses for NFS server
    allIps = getAllNfsServerIpAddresses(ctx)

    # Need an OC login to get worker node address
    ocp = Ocp(ctx, login="******", verify=True)
    worker = ocp.getWorkerNodeList()[0]

    # Run Python script tools/modules/nfs-ping-test on helper node (in-line)
    cmdShell = CmdShell()
    host = ctx.cf.ocp.helper.host.name
    user = ctx.cr.ocp.helper.user
    repo = ctx.cf.build.repo.root
    toolCmd = f'python3 - <{repo}/tools/modules/nfs-ping-test {worker} {allIps}'

    cmdSsh = CmdSsh(ctx, host, user, reuseCon=False)
    runCmd, secr = cmdSsh.getSshCmdAndSecrets(withLogin=True)

    ipAddr = cmdShell.run(f'{runCmd} {toolCmd}', secrets=secr).out
    logging.debug(
        f"Running shell cmd: '{runCmd} {toolCmd}' returns '{ipAddr}'")
    if ipAddr == 'None':
        message = "Could not identify valid IP address for the NFS server"
        message += f"on worker node {worker}.\n"
        fail(message)

    del ocp
    return ipAddr
 def __init__(self, ctx):
     self._ctx = ctx
     self._host = None
     self._user = None
     self._cmdShell = CmdShell()
     self._cmdSsh = None
     self._remoteCopy = None
     self._flavor = None
     self._description = None
Пример #4
0
    def podmanOcpRegistryLogin(self):
        """ Log into the default registry of an OpenShift cluster """

        out = CmdShell().run(
            'podman login'
            ' --tls-verify=false'
            ' -u $(oc whoami) -p $(oc whoami --show-token)'
            f' default-route-openshift-image-registry.apps.{self._domain}').out

        if not out.startswith('Login Succeeded!'):
            fail('podman login failed')
Пример #5
0
def getPublicKey(ctx, hname, user):
    """ Get the public key from a public key file of a specifc user at a specific host """

    userFull = f'{user.name}@{hname}'

    # Prepare command execution and determine path of public key file

    if hname == getBuildHost().name:
        cmd = CmdShell()
        defaultPubKeyPath = f'{Path.home()}/.ssh/id_rsa.pub'
    else:
        cmd = CmdSsh(ctx, hname, user)
        defaultPubKeyPath = f'{getHomeDir(ctx, hname, user)}/.ssh/id_rsa.pub'

    if f'{user.sshid}':
        pubKeyPath = f'{user.sshid}.pub'
    else:
        pubKeyPath = defaultPubKeyPath

    # Read public key file

    res = cmd.run(f'cat {pubKeyPath}')

    if res.rc != 0:
        fail(
            f"Could not get public key record of user '{userFull}' from file '{pubKeyPath}'"
        )

    # Get the public key from the public key file content

    info = _PublicKeyInformation(hname, user, pubKeyPath)

    pubKeys = _PublicKeys(res.out, info, keepAll=False)

    logging.debug(f'pubKeys >>>\n{pubKeys}\n<<< pubKeys')

    if pubKeys.numKeys() == 0:
        fail(f'Public key file of {userFull} does not contain any key record')

    if pubKeys.numKeys() > 1:
        records = '\n\n'.join(pubKeys)
        fail(f"Public key file '{pubKeyPath}' of {userFull}"
             f" contains multiple records:\n\n{records}")

    pubKey = pubKeys.getKey(0)

    logging.debug(f'Public key for {userFull}: >>>\n{pubKey}\n<<<')

    return pubKey
Пример #6
0
 def getAppNames(self):
     """ Get the deployment app names  """
     res = CmdShell().run(
         'oc get pods -o template --template "{{range .items}}{{.metadata.labels.app}} {{end}}"'
     )
     if res.rc > 0:
         return []
     return res.out.split()
Пример #7
0
    def getProject(self):
        """ get the project name from OpenShift """
        res = CmdShell().run(
            f"oc get project {self._project}"
            " -o custom-columns=NAME:.metadata.name --no-headers")

        if res.rc > 0:
            return ""
        return res.out
Пример #8
0
    def getSecret(self):
        """ get the secret from OpenShift """
        res = CmdShell().run(
            f"oc get secret --namespace {self._project}"
            f" --field-selector 'metadata.name={self._ocp.containers.di.secret}'"
            " -o custom-columns=NAME:.metadata.name --no-headers")

        if res.rc > 0:
            return ""
        return res.out
Пример #9
0
    def getWorkerNodeList(self):
        """ get the list of worker nodes from OpenShift """
        res = CmdShell().run('oc get nodes'
                             ' --selector="node-role.kubernetes.io/worker"'
                             " -o template --template"
                             " '{{range .items}}{{.metadata.name}} {{end}}'")

        if res.rc > 0:
            return []
        return res.out.split()
Пример #10
0
    def getNodePortList(self):
        """ Get the node ports on the worker node which can be used to connect to the SAP system """
        res = CmdShell().run(
            f'oc get service {self._appName}-np'
            ' -o template --template "{{range .spec.ports}}{{.name}}:{{.nodePort}} {{end}}"'
        )

        if res.rc > 0:
            return []
        return res.out.split()
def _runCmd(cmd):
    result = CmdShell().run(cmd)
    if result.rc != 0:
        msg = ''
        msg += f"Command '{cmd}' failed"
        msg += f'\n  stdout: >>>{result.out}<<<'
        msg += f'\n  stderr: >>>{result.err}<<<'
        msg += f'\n  rc: {result.rc}'
        fail(msg)
    return result
Пример #12
0
 def ocLogin(self, user=""):
     """ Log into an OpenShift cluster with given user """
     if not user:
         return self._result
     secrets = [user.password]
     return CmdShell().run(
         'oc login'
         ' --insecure-skip-tls-verify=true'
         f' https://api.{self._domain}:6443'
         f' -u {user.name}'
         ' -p :0:', secrets)
Пример #13
0
    def ocServiceAccountExists(self):
        """ Return True if Service Account exists for ocp-project """
        res = CmdShell().run(
            "oc get sa"
            f" --namespace {self._project}"
            f" --field-selector 'metadata.name={self._ocp.sa.name}'"
            " -o custom-columns=NAME:.metadata.name"
            " --no-headers")

        if not self._ocp.sa.name in res.out:
            return False
        return True
Пример #14
0
def isRepoAccessible(repository):
    """ Returns True if repository is accessible, otherwise False """
    if repository == "":
        return True

    cmd = f'dnf repolist --enabled | grep {repository}'
    out = CmdShell().run(cmd).out
    if out != "":
        logging.debug(f'Access to repository {repository} is enabled')
        return True
    logging.debug(f'Cannot access repository {repository}')
    return False
 def _runRsync(self, source, filterFilePath, verbose, dryRun):
     logging.debug(f'source: >>>{source}<<<')
     cmdShell = CmdShell()
     cmd = 'rsync -a --relative'
     cmd += f' -e "{self._rsyncSsh}"'
     if verbose > 0:
         cmd += ' -'+'v'*verbose
     cmd += f' -f "merge {filterFilePath}"'
     if dryRun:
         cmd += ' -n'
     if not isinstance(source, list):
         cmd += f' {self._user.name}@{self._host}:{source} ./'
         cmdShell.run(cmd, self._rsyncSshSecrets)
     else:
         with tempfile.NamedTemporaryFile(mode='w') as tfh:
             tfh.write("\n".join(str(fn) for fn in source))
             tfh.flush()
             logging.debug(f"Contents of file '{tfh.name}':")
             logging.debug('>>>')
             # pylint: disable=unspecified-encoding
             with open(tfh.name) as rfh:
                 logging.debug(rfh.read())
             logging.debug('<<<')
             cmd += f' -r --files-from={tfh.name}'
             cmd += f' {self._user.name}@{self._host}:/ ./'
             cmdShell.run(cmd, self._rsyncSshSecrets)
Пример #16
0
    def ocApply(self, file, printRunTime=False):
        """ Apply a configuration to a resource """

        cmd = f"oc apply -f {file}"
        if printRunTime:
            cmd = "time " + cmd
        res = CmdShell().run(cmd)

        if res.rc == 0:
            logging.debug(f"Configuration file {file} successfully applied")
        else:
            logging.debug(f"Error applying configuration file {file}")
        return res
Пример #17
0
    def ocDelete(self, file, printRunTime=False):
        """ Delete a configuration """

        cmd = f"oc delete -f {file}"
        if printRunTime:
            cmd = "time " + cmd
        res = CmdShell().run(cmd)

        if res.rc == 0:
            logging.debug(f"Configuration file {file} successfully removed")
        else:
            logging.debug(f"Error removing configuration file {file}")
        return res
Пример #18
0
    def containerRun(self, containerName, command, rcOk=(0, )):
        """ Run a command in a running container of given flavor """

        logging.debug(f'rcOk >>>{rcOk}<<<')

        podName = self.getPodName()

        if not podName:
            res = Command.buildResult('', 'Cannot get pod name', 1, rcOk=(1, ))

        else:
            ocCmd = self._buildOcExecCmd(podName, containerName, command)
            res = CmdShell().run(ocCmd, rcOk=rcOk)
        return res
Пример #19
0
    def getServiceAccountListForScc(self, scc):
        """ get the list of service accounts for scc from OpenShift """

        tplList = {
            "anyuid": str('{{range .groups}}{{.}} {{end}}'),
            "hostmount-anyuid": str('{{range .users}}{{.}} {{end}}')
        }

        template = tplList[scc]

        res = CmdShell().run(f"oc adm policy who-can use scc {scc} -o template"
                             f" --template='{template}'"
                             f" --namespace={self._project}")

        if res.rc > 0:
            return []
        return res.out.split()
Пример #20
0
    def getHdbConnectSecretUser(self):
        """ Get credentials currently stored in OCP secret of name ctx.cf.ocp.containers.di.secret

            Returns an object 'user' where

            - 'user.name'     holds the retrieved user name
            - 'user.password' holds the retrieved password

            in case of success

            Returns None in case of failure (also if ctx.cf.ocp.containers.di.secret is not defined)
        """

        secretName = self._ocp.containers.di.secret

        template = str(
            '{{(index (index .items 0).metadata.annotations'
            ' "kubectl.kubernetes.io/last-applied-configuration")}}')

        res = CmdShell().run(f'oc get secret'
                             f" --namespace '{self._project}'"
                             f" --field-selector 'metadata.name={secretName}'"
                             f" -o template --template '{template}'")

        if res.rc == 0:
            try:
                secretData = yaml.load(res.out,
                                       Loader=yaml.Loader)['stringData']

                user = types.SimpleNamespace()
                user.name = secretData['HDB_DBUSER']
                user.password = secretData['HDB_DBUSERPWD']

            except KeyError as kex:
                user = None
                logging.debug(
                    f"Could not evaluate secret data of OCP secret '{secretName}' ({kex})"
                )

        else:
            user = None
            logging.debug(
                f"Could not retrieve secret data from OCP secret '{secretName}'"
            )

        return user
Пример #21
0
    def __init__(self, ctx, create=False):

        self._noFileMsg = f"Credentials file '{ctx.ar.creds_file}' does not exist"

        # Determine encryption status of ctx.ar.creds_file
        # The file is considered not to be encrypted
        # - if a new credentials file is created and CLI argument
        #   '--unencypted' is set
        # - otherwise, if the file exists, encryption status of the file is
        #   derived from the file type returned by the Linux 'file' command,
        #   taking into consideration that the file maybe a symlink.

        credsfile = os.path.realpath(ctx.ar.creds_file)

        if create:
            # This case can only occur if the calling tool is 'tools/creds -n'
            self._unencrypted = ctx.ar.unencrypted

        elif pathlib.Path(credsfile).is_file():
            out = CmdShell().run(f'file -b {credsfile} --mime-type').out
            self._unencrypted = 'application/pgp' not in out

        else:
            # This case will lead to abort of the calling tool since
            # super().__init__() will finally try to read the non-existing file.
            # Nevertheless we need to set attribute self._unencrypted since it
            # is accessed before the calling tool is aborted.
            # Set it to True since this avoids some unnecessary actions.
            self._unencrypted = True

        self._gpg = self._getGpg()
        self._recipient = ctx.ar.recipient if hasattr(ctx.ar,
                                                      'recipient') else None
        self._passphrase = os.getenv('SOOS_CREDS_PASSPHRASE')

        super().__init__(ctx, './creds.yaml.template', ctx.ar.creds_file,
                         create)

        if create:
            return

        logging.debug(f"Assuming file '{ctx.ar.creds_file}'"
                      f" is{' not' if self._unencrypted else ''} encrypted")
Пример #22
0
def getRpmFileForPackage(packageName, path):
    """ Return filename for specified package """

    # do not use fail function here, cause verify-config uses this function too
    if os.path.exists(path):
        pathContent = os.listdir(path)
        if len(pathContent) < 1:
            raise RpmFileNotFoundException(path, packageName, 'is empty.')
        cmd = 'rpm -qp --queryformat "%{NAME}" '
        for file in pathContent:
            if os.path.isfile(path + '/' + file):
                # check if rpm is found
                packageNameFromRpm = CmdShell().run(cmd + path + '/' + file).out
                if packageNameFromRpm == packageName:
                    return file
    else:
        raise RpmFileNotFoundException(path, packageName, 'does not exist.')
    raise RpmFileNotFoundException(path, packageName,
                                   'does not contain a matching rpm package file.')
Пример #23
0
    def _getPodProperty(self, propertyName, propertySelector):
        """ Get a property of the pod in which our current deployment is running """

        podProperty = ''
        if not self._appName:
            fail("Internal error: appName not set")

        res = CmdShell().run(f'oc get pods --selector="app={self._appName}"'
                             ' -o template --template "{{range .items}}{{' +
                             propertySelector + '}}{{end}}"')

        if res.rc == 0:
            podProperty = res.out.strip()
            logging.debug(f"Pod property '{propertyName}': '{podProperty}'")

        else:
            logging.debug(f"Could not get pod property '{propertyName}'"
                          f" for app '{self._appName}' (reason: {res.err})")

        return podProperty
class Builder():
    """ Build container images """

    # pylint: disable=too-many-instance-attributes

    def __init__(self, ctx):
        self._ctx = ctx
        self._host = None
        self._user = None
        self._cmdShell = CmdShell()
        self._cmdSsh = None
        self._remoteCopy = None
        self._flavor = None
        self._description = None

    def buildImage(self, sidU, host, user):
        """ Build image """

        # pylint: disable=too-many-locals,too-many-statements

        repoRoot = self._ctx.cf.build.repo.root
        buildTmpRoot = self._ctx.ar.temp_root
        buildDir = self._ctx.ar.build_directory
        keepFiles = self._ctx.ar.keep_files

        # Initialize ssh connection

        if not self._cmdSsh or host != self._host or user != self._user:
            # Initialize only if not yet initialized or if connection parameters have changed
            if self._cmdSsh:
                del self._cmdSsh
            self._cmdSsh = CmdSsh(self._ctx, host, user)

        # Initialize remote copy connection

        if not self._remoteCopy or host != self._host or user != self._user:
            # Initialize only if not yet initialized or if connection parameters have changed
            if self._remoteCopy:
                del self._remoteCopy
            self._remoteCopy = RemoteCopy(self._ctx, host, user)

        self._host = host
        self._user = user

        # System ID

        sidL = sidU.lower()

        logging.debug(f"sidU: '{sidU}'")
        logging.debug(f"sidL: '{sidL}'")

        # Directories

        dirs = types.SimpleNamespace()
        dirs.repoRoot = repoRoot
        if buildDir and len(buildDir) != 0:
            dirs.build = buildDir
        else:
            self._cmdShell.run(f'mkdir -p "{buildTmpRoot}"')
            dirs.build = self._cmdShell.run(
                f'mktemp -d -p "{buildTmpRoot}" '
                f'-t soos-build-{self._flavor}.XXXXXXXXXX').out
        dirs.usrSapReal = self._getUsrSapReal()
        dirs.sapmnt = self._ctx.cf.refsys.nws4.base.sapmnt

        self._setDirsFlavor(sidU, dirs)

        logging.debug(f"dirs: '{dirs}'")

        # Image properties

        image = types.SimpleNamespace()
        image.name = f'localhost/soos-{sidL}'
        image.version = 'latest'
        image.tag = f'{image.name}:{image.version}'
        image.date = date.today().strftime('%Y-%m-%d')
        image.description = self._description  # Must be set by derived class
        with pushd(dirs.repoRoot):
            image.commit = self._cmdShell.run('git log --pretty="%H" -1').out
            image.branch = self._cmdShell.run(
                'git rev-parse --abbrev-ref HEAD').out

        logging.debug(f"image: '{image}'")

        # OS user properties

        (sapadm, sidadm, sapsysGid) = self._getOsUserProperties(sidL)

        logging.debug(f"sapadm   : '{sapadm}'")
        logging.debug(f"sidadm   : '{sidadm}'")
        logging.debug(f"sapsysGid: '{sapsysGid}'")

        # Misc

        buildCmd = 'podman'
        remoteOs = 'linux' + self._cmdSsh.run('uname -m').out

        # Start build process

        with tempfile.TemporaryDirectory() as dirs.tmp:
            logging.debug(f"Created temporary directory '{dirs.tmp}'")
            self._cleanupAtStart(dirs, keepFiles)
            self._genBuildContext(sidU, dirs, sapadm, sidadm, sapsysGid, host,
                                  remoteOs)
            containerfile = self._genContainerfile(sidU, dirs, image, sapadm,
                                                   sidadm, sapsysGid)
            self._buildImage(buildCmd, dirs, image, containerfile)
            self._cleanupAtEnd(dirs)

    def _getUsrSapReal(self):
        # Check whether /usr/sap is a real directory or a symlink to another directory
        usrSapReal = self._cmdSsh.run('readlink /usr/sap').out
        if len(usrSapReal) != 0:
            logging.info(
                f"Detected that '/usr/sap' is a symbolic link to '{usrSapReal}'"
            )
        else:
            usrSapReal = '/usr/sap'
        logging.debug(f"usrSapReal: '{usrSapReal}'")
        return usrSapReal

    def _setDirsFlavor(self, sidU, dirs):
        # Flavor specific directories
        # pylint: disable=unused-argument
        fail(
            'This function must be overwritten by derived flavor specific builder class.'
        )

    def _getOsUserProperties(self, sidL):
        # Get properties of sapadm and <sid>adm from remote host /etc/passwd

        sapadm = types.SimpleNamespace()
        (_d1, _d2, sapadm.uid, sapsysGid, sapadm.comment, sapadm.home,
         sapadm.shell
         ) = self._cmdSsh.run('grep "^sapadm:" /etc/passwd').out.split(':')

        sidadm = types.SimpleNamespace()
        (_d1, _d2, sidadm.uid, _d4, sidadm.comment, sidadm.home, sidadm.shell
         ) = self._cmdSsh.run(f'grep "^{sidL}adm:" /etc/passwd').out.split(':')

        logging.debug(f'Returning {sapadm}, {sidadm}, {sapsysGid}')

        return (sapadm, sidadm, sapsysGid)

    def _cleanupAtStart(self, dirs, keepFiles):
        # Remove previously copied files if not explicitly asked to keep them
        if not keepFiles:
            logging.info(
                f"##### Cleaning up build directoy '{dirs.build}' #####")
            with pushd(dirs.build):
                self._cmdShell.run('rm -rf ..?* .[!.]* *')

    def _genBuildContext(self, sidU, dirs, sapadm, sidadm, sapsysGid, host,
                         remoteOs):
        # Generate podman build context
        # pylint: disable=too-many-arguments
        filterFilePath = f'{dirs.tmp}/rsync-filter'
        logging.debug(f"filterFilePath: {filterFilePath}")
        try:
            # pylint: disable=invalid-name, unspecified-encoding
            with open(filterFilePath, 'w') as fh:
                print(self._getRsyncFilter(sidU, dirs, remoteOs), file=fh)
        except IOError:
            fail(f"Error writing to file {filterFilePath}")

        self._genBuildContextFlavor(sidU, dirs, sapadm, sidadm, sapsysGid,
                                    host, filterFilePath)

    def _getRsyncFilter(self, sidU, dirs, remoteOs):
        # Get filter for selective copy depending on flavor
        # pylint: disable=unused-argument
        fail(
            'This function must be overwritten by derived flavor specific builder class.'
        )

    def _genBuildContextFlavor(self, sidU, dirs, sapadm, sidadm, sapsysGid,
                               host, filterFilePath):
        # Flavor dependent actions for build context generation
        # pylint: disable=unused-argument,too-many-arguments
        fail(
            'This function must be overwritten by derived flavor specific builder class.'
        )

    def _genContainerfile(self, sidU, dirs, image, sapadm, sidadm, sapsysGid):
        # Generate containerfile from template depending on flavor
        # MUST RUN AFTER BUILD CONTEXT SETUP
        # pylint: disable=too-many-arguments
        logging.info("##### Generating Containerfile #####")

        sidL = sidU.lower()

        # Common parameters
        if dirs.usrSapReal != '/usr/sap':
            usrSapLinkCmd = f'ln -s {dirs.usrSapReal} /usr/sap'
        else:
            usrSapLinkCmd = 'true'

        # get optional packages
        packages = getattr(self._ctx.cf.images, self._flavor).packages
        pkgParams = self._getOptionalPackageParams(packages, dirs)

        params = {
            'IMAGE_BRANCH': image.branch,
            'IMAGE_COMMIT': image.commit,
            'IMAGE_DATE': image.date,
            'IMAGE_DESCRIPTION': image.description,
            'IMAGE_VERSION': image.version,
            'SAPADM_COMMENT': sapadm.comment,
            'SAPADM_HOME': sapadm.home,
            'SAPADM_SHELL': sapadm.shell,
            'SAPADM_UID': sapadm.uid,
            'SAPMNT': dirs.sapmnt,
            'SAPSYS_GID': sapsysGid,
            'sid': sidL,
            'SID': sidU,
            'SIDADM_COMMENT': sidadm.comment,
            'SIDADM_HOME': sidadm.home,
            'SIDADM_SHELL': sidadm.shell,
            'SIDADM_UID': sidadm.uid,
            'USR_SAP_REAL': dirs.usrSapReal,
            'USR_SAP_LINK_CMD': usrSapLinkCmd,
            'INSTALL_OPT_PACKAGES': pkgParams.installOptPackagesDnf,
            'COPY_OPT_PACKAGE_FILES': pkgParams.copyOptPackageFiles,
            'INSTALL_OPT_PACKAGE_FILES': pkgParams.installOptPackageFiles
        }

        params.update(self._getContainerfileParams(sidU, dirs))
        containerfile = f'{dirs.tmp}/containerfile'
        template = f'{dirs.repoRoot}/openshift/images/{self._flavor}/containerfile.template'
        genFileFromTemplate(template, containerfile, params)
        try:
            # pylint: disable=invalid-name, unspecified-encoding
            with open(containerfile) as fh:
                logging.debug(
                    f"Contents of '{containerfile}': >>>\n{fh.read()}<<<")
        except IOError:
            fail(f"Error reading from {containerfile}")
        return containerfile

    def _getContainerfileParams(self, sidU, dirs):
        # Non-common containerfile template parameters depending on flavor
        # pylint: disable=unused-argument
        fail(
            'This function must be overwritten by derived flavor specific builder class.'
        )

    def _buildImage(self, buildCmd, dirs, image, containerfile):
        # Build image
        # MUST RUN AFTER BUILD CONTEXT SETUP
        # pylint: disable=no-self-use
        logging.info("##### Building image #####")
        with pushd(dirs.build):
            self._cmdShell.run(
                f'{buildCmd} build -t {image.tag} -f "{containerfile}" .')

    def _getOptionalPackageParams(self, packages, dirs):
        # Check if optional packages must be installed
        # and set them
        pkgParams = types.SimpleNamespace()
        pkgParams.installOptPackagesDnf = ''
        pkgParams.copyOptPackageFiles = ''
        pkgParams.installOptPackageFiles = ''

        if len(packages) > 0:
            self._addDependencies(packages, pkgParams)
            self._addDnfInstallablePackages(packages, pkgParams)
            self._addRpmPackages(packages, pkgParams, dirs)
        return pkgParams

    def _addDependencies(self, packages, pkgParams):
        # Set dependencies for optional packages
        firstRun = pkgParams.installOptPackagesDnf == ""

        for package in packages:
            if len(package.dependencies) > 0:
                if firstRun:
                    pkgParams.installOptPackagesDnf = 'RUN  dnf -y install'
                    firstRun = False
                else:
                    pkgParams.installOptPackagesDnf += ' && \\' + '\n'
                    pkgParams.installOptPackagesDnf += '     dnf -y install'

                for dependency in package.dependencies:
                    logging.debug(f"Adding dependency '{dependency}' " +
                                  f"for package '{package.packageName}'")
                    pkgParams.installOptPackagesDnf += f' {dependency}'

    def _addDnfInstallablePackages(self, packages, pkgParams):
        # set all packages to be installed using dnf
        firstRun = pkgParams.installOptPackagesDnf == ""
        for package in packages:
            if package.dnfInstallable:
                logging.debug(
                    f'package {package.packageName} installable via dnf install'
                )

                if firstRun:
                    pkgParams.installOptPackagesDnf = 'RUN  dnf -y install'
                    firstRun = False
                else:
                    pkgParams.installOptPackagesDnf += ' && \\' + '\n'
                    pkgParams.installOptPackagesDnf += '     dnf -y install'
                if package.repository != "":
                    pkgParams.installOptPackagesDnf += f' --enablerepo={package.repository}'
                    logging.debug(
                        f'enabling repository    : {package.repository}')
                pkgParams.installOptPackagesDnf += f' {package.packageName}'

    def _addRpmPackages(self, packages, pkgParams, dirs):
        # set all packages which must be copied and installed using rpm
        firstRun = pkgParams.copyOptPackageFiles == ""
        for package in packages:
            if not package.dnfInstallable:
                logging.debug(
                    f'package {package.packageName} must be installed via rpm')
                if firstRun:
                    pkgParams.copyOptPackageFiles = 'COPY '
                    pkgParams.installOptPackageFiles = 'RUN  '
                    firstRun = False
                else:
                    pkgParams.copyOptPackageFiles += ' && \\' + '\n' + '     '
                    pkgParams.installOptPackageFiles += ' && \\' + '\n' + '     '

                try:
                    rpmFileName = getRpmFileForPackage(package.packageName,
                                                       dirs.defaultPackagesDir)
                    pkgParams.copyOptPackageFiles += f'{dirs.defaultPackagesDir}'
                    pkgParams.copyOptPackageFiles += f'/{rpmFileName} / '
                    pkgParams.installOptPackageFiles += f'rpm -i /{rpmFileName} && \\' + '\n'
                    pkgParams.installOptPackageFiles += f'     rm /{rpmFileName}'
                except RpmFileNotFoundException as exp:
                    fail(exp.errorText)

    def _cleanupAtEnd(self, dirs):
        # Cleanup after image build
        with pushd(dirs.repoRoot):
            # self._cmdShell.run(f'\\rm -rf {dirs.build}')
            pass
Пример #25
0
 def setProject(self):
     """ Set project """
     return CmdShell().run(f"oc project {self._project}")
Пример #26
0
 def serviceDelete(self, serviceName):
     """ deletes the specified service """
     if self.serviceExists(serviceName):
         res = CmdShell().run(f"oc delete service {serviceName}")
         print(res)
Пример #27
0
 def serviceExists(self, serviceName):
     """ Returns True if the specified NodePort Service exists """
     res = CmdShell().run(f"oc get service {serviceName}")
     return res.rc == 0
Пример #28
0
 def isProjectExisting(self):
     """ Does the specified oc project exist """
     res = CmdShell().run(f"oc get project {self._project}")
     return res.rc == 0
Пример #29
0
 def createProject(self):
     """ Create project  """
     print(f"creating project: {self._project}")
     return CmdShell().run(f"oc new-project {self._project}")
Пример #30
0
 def ocLogout(self):
     """ Logout from OpenShift Cluster """
     return CmdShell().run('oc logout').rc