mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
commit
1023f9b03f
165
salt/modules/rpmbuild.py
Normal file
165
salt/modules/rpmbuild.py
Normal file
@ -0,0 +1,165 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
RPM Package builder system
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
This system allows for all of the components to build rpms safely in chrooted
|
||||
environments. This also provides a function to generate yum repositories
|
||||
|
||||
This module impliments the pkgbuild interface
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
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
|
||||
|
||||
__virtualname__ = 'pkgbuild'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only if rpmdevtools, createrepo and mock are available
|
||||
'''
|
||||
if salt.utils.which('mock'):
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _mk_tree():
|
||||
'''
|
||||
Create the rpm build tree
|
||||
'''
|
||||
basedir = tempfile.mkdtemp()
|
||||
paths = ['BUILD', 'RPMS', 'SOURCES', 'SPECS', 'SRPMS']
|
||||
for path in paths:
|
||||
full = os.path.join(basedir, path)
|
||||
os.makedirs(full)
|
||||
return basedir
|
||||
|
||||
|
||||
def _get_spec(tree_base, spec, template, saltenv='base'):
|
||||
'''
|
||||
Get the spec file and place it in the SPECS dir
|
||||
'''
|
||||
spec_tgt = os.path.basename(spec)
|
||||
dest = os.path.join(tree_base, 'SPECS', spec_tgt)
|
||||
return __salt__['cp.get_file'](
|
||||
spec,
|
||||
dest,
|
||||
saltenv=saltenv,
|
||||
template=template)
|
||||
|
||||
|
||||
def _get_src(tree_base, source, saltenv='base'):
|
||||
'''
|
||||
Get the named sources and place them into the tree_base
|
||||
'''
|
||||
parsed = _urlparse(source)
|
||||
sbase = os.path.basename(source)
|
||||
dest = os.path.join(tree_base, 'SOURCES', sbase)
|
||||
if parsed.scheme:
|
||||
lsrc = __salt__['cp.get_file'](source, dest, saltenv=saltenv)
|
||||
else:
|
||||
shutil.copy(source, dest)
|
||||
|
||||
|
||||
def make_src_pkg(dest_dir, spec, sources, template=None, saltenv='base'):
|
||||
'''
|
||||
Create a source rpm from the given spec file and sources
|
||||
|
||||
CLI Example:
|
||||
|
||||
salt '*' pkgbuild.make_src_pkg /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 SOURCE package and place it in
|
||||
/var/www/html/ on the minion
|
||||
'''
|
||||
tree_base = _mk_tree()
|
||||
spec_path = _get_spec(tree_base, spec, template, saltenv)
|
||||
if isinstance(sources, str):
|
||||
sources = sources.split(',')
|
||||
for src in sources:
|
||||
_get_src(tree_base, src, saltenv)
|
||||
cmd = 'rpmbuild --define "_topdir {0}" -bs {1}'.format(tree_base, spec_path)
|
||||
__salt__['cmd.run'](cmd)
|
||||
srpms = os.path.join(tree_base, 'SRPMS')
|
||||
ret = []
|
||||
if not os.path.isdir(dest_dir):
|
||||
os.makedirs(dest_dir)
|
||||
for fn_ in os.listdir(srpms):
|
||||
full = os.path.join(srpms, fn_)
|
||||
tgt = os.path.join(dest_dir, fn_)
|
||||
shutil.copy(full, tgt)
|
||||
ret.append(tgt)
|
||||
return ret
|
||||
|
||||
|
||||
def build(runas, tgt, dest_dir, spec, sources, template, saltenv='base'):
|
||||
'''
|
||||
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.make_src_pkg 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, template, saltenv)
|
||||
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 -r {0} --rebuild {1} --resultdir {2}'.format(
|
||||
tgt,
|
||||
srpm,
|
||||
results_dir)
|
||||
__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:
|
||||
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)
|
||||
shutil.rmtree(srpm_dir)
|
||||
return ret
|
||||
|
||||
|
||||
def make_repo(repodir):
|
||||
'''
|
||||
Given the repodir, create a yum repository out of the rpms therein
|
||||
|
||||
CLI Example::
|
||||
|
||||
salt '*' pkgbuild.make_repo /var/www/html/
|
||||
'''
|
||||
cmd = 'createrepo {0}'.format(repodir)
|
||||
__salt__['cmd.run'](cmd)
|
144
salt/states/pkgbuild.py
Normal file
144
salt/states/pkgbuild.py
Normal file
@ -0,0 +1,144 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
The pkgbuild state is the front of Salt package building backend. It
|
||||
automatically
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
salt_2015.5.2:
|
||||
pkgbuild.built:
|
||||
- runas: thatch
|
||||
- results:
|
||||
- salt-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- salt-api-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- salt-cloud-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- salt-master-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- salt-minion-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- salt-ssh-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- salt-syndic-2015.5.2-2.el7.centos.noarch.rpm
|
||||
- dest_dir: /tmp/pkg
|
||||
- spec: salt://pkg/salt/spec/salt.spec
|
||||
- template: jinja
|
||||
- tgt: epel-7-x86_64
|
||||
- sources:
|
||||
- salt://pkg/salt/sources/logrotate.salt
|
||||
- salt://pkg/salt/sources/README.fedora
|
||||
- salt://pkg/salt/sources/salt-2015.5.2.tar.gz
|
||||
- salt://pkg/salt/sources/salt-2015.5.2-tests.patch
|
||||
- salt://pkg/salt/sources/salt-api
|
||||
- salt://pkg/salt/sources/salt-api.service
|
||||
- salt://pkg/salt/sources/salt-master
|
||||
- salt://pkg/salt/sources/salt-master.service
|
||||
- salt://pkg/salt/sources/salt-minion
|
||||
- salt://pkg/salt/sources/salt-minion.service
|
||||
- salt://pkg/salt/sources/saltpkg.sls
|
||||
- salt://pkg/salt/sources/salt-syndic
|
||||
- salt://pkg/salt/sources/salt-syndic.service
|
||||
- salt://pkg/salt/sources/SaltTesting-2015.5.8.tar.gz
|
||||
/tmp/pkg:
|
||||
pkgbuild.repo
|
||||
'''
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
import os
|
||||
|
||||
|
||||
def built(
|
||||
name,
|
||||
runas,
|
||||
dest_dir,
|
||||
spec,
|
||||
sources,
|
||||
template,
|
||||
tgt,
|
||||
results=None,
|
||||
always=False,
|
||||
saltenv='base'):
|
||||
'''
|
||||
Ensure that the named package is built and exists in the named directory
|
||||
|
||||
name
|
||||
The name to track the build, the name value is otherwise unused
|
||||
|
||||
runas
|
||||
The user to run the build process as
|
||||
|
||||
dest_dir
|
||||
The directory on the minion to place the built package(s)
|
||||
|
||||
spec
|
||||
The location of the spec file (used for rpms)
|
||||
|
||||
sources
|
||||
The list of package sources
|
||||
|
||||
template
|
||||
Set to run the spec file through a templating engine
|
||||
|
||||
tgt
|
||||
The target platform to run the build on
|
||||
|
||||
results
|
||||
The names of the expected rpms that will be built
|
||||
|
||||
always
|
||||
Build with every run (good if the package is for continuous or
|
||||
nightly package builds)
|
||||
|
||||
saltenv
|
||||
The saltenv to use for files downloaded from the salt filesever
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'comment': '',
|
||||
'result': True}
|
||||
if not always:
|
||||
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.appd(fn_)
|
||||
need = results.difference(present)
|
||||
if not need:
|
||||
ret['comment'] = 'All needed packages exist'
|
||||
return ret
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Packages need to be built'
|
||||
ret['result'] = None
|
||||
return ret
|
||||
ret['changes'] = __salt__['pkgbuild.build'](
|
||||
runas,
|
||||
tgt,
|
||||
dest_dir,
|
||||
spec,
|
||||
sources,
|
||||
template,
|
||||
saltenv)
|
||||
ret['comment'] = 'Packages Built'
|
||||
return ret
|
||||
|
||||
|
||||
def repo(name):
|
||||
'''
|
||||
Make a package repository, the name is directoty to turn into a repo.
|
||||
This state is best used with onchanges linked to your package building
|
||||
states
|
||||
|
||||
name
|
||||
The directory to find packages that will be in the repository
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'comment': '',
|
||||
'result': True}
|
||||
if __opts__['test'] is True:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Package repo at {0} will be rebuilt'.format(name)
|
||||
return ret
|
||||
__salt__['pkgbuild.make_repo'](name)
|
||||
ret['changes'] = {'refresh': True}
|
||||
return ret
|
Loading…
Reference in New Issue
Block a user