mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #28632 from terminalmage/pkgbuild-fixes
Fixes/improvements to pkgbuild state/modules
This commit is contained in:
commit
0583575f82
3 changed files with 193 additions and 92 deletions
|
@ -12,16 +12,18 @@ This module impliments the pkgbuild interface
|
|||
|
||||
# import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
from salt.exceptions import SaltInvocationError
|
||||
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
# pylint: disable=import-error
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = 'pkgbuild'
|
||||
|
||||
|
@ -329,7 +331,16 @@ def make_src_pkg(dest_dir, spec, sources, env=None, template=None, saltenv='base
|
|||
return ret
|
||||
|
||||
|
||||
def build(runas, tgt, dest_dir, spec, sources, deps, env, template, saltenv='base'):
|
||||
def build(runas,
|
||||
tgt,
|
||||
dest_dir,
|
||||
spec,
|
||||
sources,
|
||||
deps,
|
||||
env,
|
||||
template,
|
||||
saltenv='base',
|
||||
log_dir='/var/log/salt/pkgbuild'): # pylint: disable=unused-argument
|
||||
'''
|
||||
Given the package destination directory, the tarball containing debian files (e.g. control)
|
||||
and package sources, use pbuilder to safely build the platform package
|
||||
|
@ -337,19 +348,24 @@ def build(runas, tgt, dest_dir, spec, sources, deps, env, template, saltenv='bas
|
|||
CLI Example:
|
||||
|
||||
Debian
|
||||
salt '*' pkgbuild.make_src_pkg deb-8-x86_64 /var/www/html/ https://raw.githubusercontent.com/saltstack/libnacl/master/pkg/deb/python-libnacl.control https://pypi.python.org/packages/source/l/libnacl/libnacl-1.3.5.tar.gz
|
||||
salt '*' pkgbuild.make_src_pkg deb-8-x86_64 /var/www/html https://raw.githubusercontent.com/saltstack/libnacl/master/pkg/deb/python-libnacl.control https://pypi.python.org/packages/source/l/libnacl/libnacl-1.3.5.tar.gz
|
||||
|
||||
This example command should build the libnacl package for Debian using pbuilder
|
||||
and place it in /var/www/html/ on the minion
|
||||
'''
|
||||
ret = {}
|
||||
if not os.path.isdir(dest_dir):
|
||||
try:
|
||||
os.makedirs(dest_dir)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
try:
|
||||
os.makedirs(dest_dir)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
dsc_dir = tempfile.mkdtemp()
|
||||
dscs = make_src_pkg(dsc_dir, spec, sources, env, template, saltenv)
|
||||
try:
|
||||
dscs = make_src_pkg(dsc_dir, spec, sources, env, template, saltenv)
|
||||
except Exception as exc:
|
||||
shutil.rmtree(dsc_dir)
|
||||
log.error('Failed to make src package')
|
||||
return ret
|
||||
|
||||
# dscs should only contain salt orig and debian tarballs and dsc file
|
||||
for dsc in dscs:
|
||||
|
@ -359,23 +375,26 @@ def build(runas, tgt, dest_dir, spec, sources, deps, env, template, saltenv='bas
|
|||
|
||||
if dsc.endswith('.dsc'):
|
||||
dbase = os.path.dirname(dsc)
|
||||
cmd = 'chown {0} -R {1}'.format(runas, dbase)
|
||||
__salt__['cmd.run'](cmd)
|
||||
|
||||
results_dir = tempfile.mkdtemp()
|
||||
cmd = 'chown {0} -R {1}'.format(runas, results_dir)
|
||||
__salt__['cmd.run'](cmd)
|
||||
try:
|
||||
__salt__['cmd.run']('chown {0} -R {1}'.format(runas, dbase))
|
||||
__salt__['cmd.run']('chown {0} -R {1}'.format(runas, results_dir))
|
||||
|
||||
cmd = 'pbuilder --create'
|
||||
__salt__['cmd.run'](cmd, runas=runas, python_shell=True)
|
||||
cmd = 'pbuilder --build --buildresult {1} {0}'.format(dsc, results_dir)
|
||||
__salt__['cmd.run'](cmd, runas=runas, python_shell=True)
|
||||
cmd = 'pbuilder --create'
|
||||
__salt__['cmd.run'](cmd, runas=runas, python_shell=True)
|
||||
cmd = 'pbuilder --build --buildresult {1} {0}'.format(
|
||||
dsc, results_dir)
|
||||
__salt__['cmd.run'](cmd, runas=runas, python_shell=True)
|
||||
|
||||
for bfile in os.listdir(results_dir):
|
||||
full = os.path.join(results_dir, bfile)
|
||||
bdist = os.path.join(dest_dir, bfile)
|
||||
shutil.copy(full, bdist)
|
||||
shutil.rmtree(results_dir)
|
||||
for bfile in os.listdir(results_dir):
|
||||
full = os.path.join(results_dir, bfile)
|
||||
bdist = os.path.join(dest_dir, bfile)
|
||||
shutil.copy(full, bdist)
|
||||
ret.setdefault('Packages', []).append(bdist)
|
||||
except Exception as exc:
|
||||
log.error('Error building from {0}: {1}'.format(dsc, exc))
|
||||
finally:
|
||||
shutil.rmtree(results_dir)
|
||||
shutil.rmtree(dsc_dir)
|
||||
return ret
|
||||
|
||||
|
|
|
@ -12,14 +12,18 @@ This module impliments the pkgbuild interface
|
|||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse # pylint: disable=no-name-in-module,import-error
|
||||
import tempfile
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
from salt.exceptions import SaltInvocationError
|
||||
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = 'pkgbuild'
|
||||
|
||||
|
@ -164,26 +168,42 @@ def make_src_pkg(dest_dir, spec, sources, env=None, template=None, saltenv='base
|
|||
return ret
|
||||
|
||||
|
||||
def build(runas, tgt, dest_dir, spec, sources, deps, env, template, saltenv='base'):
|
||||
def build(runas,
|
||||
tgt,
|
||||
dest_dir,
|
||||
spec,
|
||||
sources,
|
||||
deps,
|
||||
env,
|
||||
template,
|
||||
saltenv='base',
|
||||
log_dir='/var/log/salt/pkgbuild'):
|
||||
'''
|
||||
Given the package destination directory, the spec file source and package
|
||||
sources, use mock to safely build the rpm defined in the spec file
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt '*' pkgbuild.build mock epel-7-x86_64 /var/www/html/ https://raw.githubusercontent.com/saltstack/libnacl/master/pkg/rpm/python-libnacl.spec https://pypi.python.org/packages/source/l/libnacl/libnacl-1.3.5.tar.gz
|
||||
salt '*' pkgbuild.build mock epel-7-x86_64 /var/www/html https://raw.githubusercontent.com/saltstack/libnacl/master/pkg/rpm/python-libnacl.spec https://pypi.python.org/packages/source/l/libnacl/libnacl-1.3.5.tar.gz
|
||||
|
||||
This example command should build the libnacl package for rhel 7 using user
|
||||
mock and place it in /var/www/html/ on the minion
|
||||
'''
|
||||
ret = {}
|
||||
if not os.path.isdir(dest_dir):
|
||||
try:
|
||||
os.makedirs(dest_dir)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
srpm_dir = tempfile.mkdtemp()
|
||||
srpms = make_src_pkg(srpm_dir, spec, sources, env, template, saltenv)
|
||||
try:
|
||||
os.makedirs(dest_dir)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
srpm_dir = os.path.join(dest_dir, 'SRPMS')
|
||||
srpm_build_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
srpms = make_src_pkg(srpm_build_dir, spec, sources,
|
||||
env, template, saltenv)
|
||||
except Exception as exc:
|
||||
shutil.rmtree(srpm_build_dir)
|
||||
log.error('Failed to make src package')
|
||||
return ret
|
||||
|
||||
distset = _get_distset(tgt)
|
||||
|
||||
|
@ -197,37 +217,51 @@ def build(runas, tgt, dest_dir, spec, sources, deps, env, template, saltenv='bas
|
|||
|
||||
for srpm in srpms:
|
||||
dbase = os.path.dirname(srpm)
|
||||
cmd = 'chown {0} -R {1}'.format(runas, dbase)
|
||||
__salt__['cmd.run'](cmd)
|
||||
results_dir = tempfile.mkdtemp()
|
||||
cmd = 'chown {0} -R {1}'.format(runas, results_dir)
|
||||
__salt__['cmd.run'](cmd)
|
||||
cmd = 'mock --root={0} --resultdir={1} {2} {3} {4}'.format(
|
||||
tgt,
|
||||
results_dir,
|
||||
distset,
|
||||
noclean,
|
||||
srpm)
|
||||
__salt__['cmd.run'](cmd, runas=runas)
|
||||
for rpm in os.listdir(results_dir):
|
||||
full = os.path.join(results_dir, rpm)
|
||||
if rpm.endswith('src.rpm'):
|
||||
sdest = os.path.join(dest_dir, 'SRPMS', rpm)
|
||||
if not os.path.isdir(sdest):
|
||||
try:
|
||||
__salt__['cmd.run']('chown {0} -R {1}'.format(runas, dbase))
|
||||
__salt__['cmd.run']('chown {0} -R {1}'.format(runas, results_dir))
|
||||
cmd = 'mock --root={0} --resultdir={1} {2} {3} {4}'.format(
|
||||
tgt,
|
||||
results_dir,
|
||||
distset,
|
||||
noclean,
|
||||
srpm)
|
||||
__salt__['cmd.run'](cmd, runas=runas)
|
||||
cmd = ['rpm', '-qp', '--queryformat',
|
||||
'{0}/%{{name}}/%{{version}}-%{{release}}'.format(log_dir),
|
||||
srpm]
|
||||
log_dest = __salt__['cmd.run_stdout'](cmd, python_shell=False)
|
||||
for filename in os.listdir(results_dir):
|
||||
full = os.path.join(results_dir, filename)
|
||||
if filename.endswith('src.rpm'):
|
||||
sdest = os.path.join(srpm_dir, filename)
|
||||
try:
|
||||
os.makedirs(sdest)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
shutil.copy(full, sdest)
|
||||
elif rpm.endswith('.rpm'):
|
||||
bdist = os.path.join(dest_dir, rpm)
|
||||
shutil.copy(full, bdist)
|
||||
else:
|
||||
with salt.utils.fopen(full, 'r') as fp_:
|
||||
ret[rpm] = fp_.read()
|
||||
shutil.rmtree(results_dir)
|
||||
os.makedirs(srpm_dir)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
shutil.copy(full, sdest)
|
||||
ret.setdefault('Source Packages', []).append(sdest)
|
||||
elif filename.endswith('.rpm'):
|
||||
bdist = os.path.join(dest_dir, filename)
|
||||
shutil.copy(full, bdist)
|
||||
ret.setdefault('Packages', []).append(bdist)
|
||||
else:
|
||||
log_file = os.path.join(log_dest, filename)
|
||||
try:
|
||||
os.makedirs(log_dest)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
shutil.copy(full, log_file)
|
||||
ret.setdefault('Log Files', []).append(log_file)
|
||||
except Exception as exc:
|
||||
log.error('Error building from {0}: {1}'.format(srpm, exc))
|
||||
finally:
|
||||
shutil.rmtree(results_dir)
|
||||
shutil.rmtree(deps_dir)
|
||||
shutil.rmtree(srpm_dir)
|
||||
shutil.rmtree(srpm_build_dir)
|
||||
return ret
|
||||
|
||||
|
||||
|
|
|
@ -44,26 +44,53 @@ automatically
|
|||
'''
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
from salt.ext import six
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def built(
|
||||
name,
|
||||
runas,
|
||||
dest_dir,
|
||||
spec,
|
||||
sources,
|
||||
tgt,
|
||||
template=None,
|
||||
deps=None,
|
||||
env=None,
|
||||
results=None,
|
||||
force=False,
|
||||
always=None,
|
||||
saltenv='base'):
|
||||
def _get_missing_results(results, dest_dir):
|
||||
'''
|
||||
Return a list of the filenames specified in the ``results`` argument, which
|
||||
are not present in the dest_dir.
|
||||
'''
|
||||
try:
|
||||
present = set(os.listdir(dest_dir))
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.ENOENT:
|
||||
log.debug(
|
||||
'pkgbuild.built: dest_dir \'{0}\' does not exist'
|
||||
.format(dest_dir)
|
||||
)
|
||||
elif exc.errno == errno.EACCES:
|
||||
log.error(
|
||||
'pkgbuilt.built: cannot access dest_dir \'{0}\''
|
||||
.format(dest_dir)
|
||||
)
|
||||
present = set()
|
||||
return sorted(set(results).difference(present))
|
||||
|
||||
|
||||
def built(name,
|
||||
runas,
|
||||
dest_dir,
|
||||
spec,
|
||||
sources,
|
||||
tgt,
|
||||
template=None,
|
||||
deps=None,
|
||||
env=None,
|
||||
results=None,
|
||||
force=False,
|
||||
always=None,
|
||||
saltenv='base',
|
||||
log_dir='/var/log/salt/pkgbuild'):
|
||||
'''
|
||||
Ensure that the named package is built and exists in the named directory
|
||||
|
||||
|
@ -137,6 +164,13 @@ def built(
|
|||
|
||||
saltenv
|
||||
The saltenv to use for files downloaded from the salt filesever
|
||||
|
||||
log_dir : /var/log/salt/rpmbuild
|
||||
Root directory for log files created from the build. Logs will be
|
||||
organized by package name, version, OS release, and CPU architecture
|
||||
under this directory.
|
||||
|
||||
.. versionadded:: 2015.8.2
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
@ -151,21 +185,26 @@ def built(
|
|||
)
|
||||
force = always
|
||||
|
||||
if not force:
|
||||
if isinstance(results, str):
|
||||
results = results.split(',')
|
||||
results = set(results)
|
||||
present = set()
|
||||
if os.path.isdir(dest_dir):
|
||||
for fn_ in os.listdir(dest_dir):
|
||||
present.add(fn_)
|
||||
need = results.difference(present)
|
||||
if not need:
|
||||
ret['comment'] = 'All needed packages exist'
|
||||
return ret
|
||||
if not results:
|
||||
ret['comment'] = '\'results\' argument is required'
|
||||
ret['result'] = False
|
||||
return ret
|
||||
|
||||
if isinstance(results, six.string_types):
|
||||
results = results.split(',')
|
||||
|
||||
needed = _get_missing_results(results, dest_dir)
|
||||
if not force and not needed:
|
||||
ret['comment'] = 'All needed packages exist'
|
||||
return ret
|
||||
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Packages need to be built'
|
||||
ret['result'] = None
|
||||
if force:
|
||||
ret['comment'] = 'Packages will be force-built'
|
||||
else:
|
||||
ret['comment'] = 'The following packages need to be built: '
|
||||
ret['comment'] += ', '.join(needed)
|
||||
return ret
|
||||
|
||||
# Need the check for None here, if env is not provided then it falls back
|
||||
|
@ -173,6 +212,7 @@ def built(
|
|||
if env is not None and not isinstance(env, dict):
|
||||
ret['comment'] = ('Invalidly-formatted \'env\' parameter. See '
|
||||
'documentation.')
|
||||
ret['result'] = False
|
||||
return ret
|
||||
|
||||
ret['changes'] = __salt__['pkgbuild.build'](
|
||||
|
@ -184,8 +224,16 @@ def built(
|
|||
deps,
|
||||
env,
|
||||
template,
|
||||
saltenv)
|
||||
ret['comment'] = 'Packages Built'
|
||||
saltenv,
|
||||
log_dir)
|
||||
|
||||
needed = _get_missing_results(results, dest_dir)
|
||||
if needed:
|
||||
ret['comment'] = 'The following packages were not built: '
|
||||
ret['comment'] += ', '.join(needed)
|
||||
ret['result'] = False
|
||||
else:
|
||||
ret['comment'] = 'All needed packages were built'
|
||||
return ret
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue