|
Packit Service |
deda86 |
#!/usr/bin/env python3
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
# Copyright 2013 Red Hat Inc., Durham, North Carolina.
|
|
Packit |
517ee8 |
# All Rights Reserved.
|
|
Packit |
517ee8 |
#
|
|
Packit |
517ee8 |
# This library is free software; you can redistribute it and/or
|
|
Packit |
517ee8 |
# modify it under the terms of the GNU Lesser General Public
|
|
Packit |
517ee8 |
# License as published by the Free Software Foundation; either
|
|
Packit |
517ee8 |
# version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
517ee8 |
#
|
|
Packit |
517ee8 |
# This library is distributed in the hope that it will be useful,
|
|
Packit |
517ee8 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
517ee8 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
517ee8 |
# Lesser General Public License for more details.
|
|
Packit |
517ee8 |
#
|
|
Packit |
517ee8 |
# You should have received a copy of the GNU Lesser General Public
|
|
Packit |
517ee8 |
# License along with this library; if not, write to the Free Software
|
|
Packit |
517ee8 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
517ee8 |
#
|
|
Packit |
517ee8 |
# Authors:
|
|
Packit |
517ee8 |
# Martin Preisler <mpreisle@redhat.com>
|
|
Packit |
517ee8 |
# Vratislav Podzimek <vpodzime@redhat.com>
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
import locale
|
|
Packit |
517ee8 |
# We shall always behave the same, regardless of locale
|
|
Packit |
517ee8 |
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
import argparse
|
|
Packit |
517ee8 |
import string
|
|
Packit |
517ee8 |
import os.path
|
|
Packit |
517ee8 |
import shutil
|
|
Packit |
517ee8 |
import datetime
|
|
Packit |
517ee8 |
import tempfile
|
|
Packit |
517ee8 |
import subprocess
|
|
Packit |
517ee8 |
import sys
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
class CannotContinueError(Exception):
|
|
Packit |
517ee8 |
"""Exception class for cases where processing cannot continue."""
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
pass
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if subprocess.call(["rpmbuild", "--version"], stdout = sys.stdout, stderr = sys.stderr) != 0:
|
|
Packit |
517ee8 |
sys.stderr.write("Could not execute `rpmbuild --version`. "
|
|
Packit |
517ee8 |
"Please make sure it's installed (often packaged as 'rpm-build').\n")
|
|
Packit |
517ee8 |
sys.exit(1)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
def get_rpmbuild_paths():
|
|
Packit |
517ee8 |
sources = subprocess.check_output(["rpm", "--eval", "%{_sourcedir}"]).strip().decode('utf-8')
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if not os.path.exists(sources):
|
|
Packit |
517ee8 |
if subprocess.call(["rpmdev-setuptree"], stdout = sys.stdout, stderr = sys.stderr) != 0:
|
|
Packit |
517ee8 |
raise CannotContinueError("Failed to setup rpmbuild tree. Please make sure you have rpmdev-setuptree "
|
|
Packit |
517ee8 |
"installed, or set it up manually. The SOURCES directory (%%{_sourcedir}) was expected at "
|
|
Packit |
517ee8 |
"'%s'" % (sources))
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
rpm = subprocess.check_output(["rpm", "--eval", "%{_rpmdir}"]).strip().decode('utf-8')
|
|
Packit |
517ee8 |
srpm = subprocess.check_output(["rpm", "--eval", "%{_srcrpmdir}"]).strip().decode('utf-8')
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if not os.path.exists(rpm) or not os.path.exists(srpm):
|
|
Packit |
517ee8 |
sys.stderr.write("The SOURCES rpmbuild directory exists but RPM or SRPM do not. Please make "
|
|
Packit |
517ee8 |
"sure your rpmbuild tree is setup correctly. Delete it and it will be created automatically.\n")
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return sources, rpm, srpm
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
def copy_sources_to_rpmbuild(rpmbuild_sources_path, files):
|
|
Packit |
517ee8 |
for f in files:
|
|
Packit |
517ee8 |
shutil.copyfile(f.name, "%s/%s" % (rpmbuild_sources_path, os.path.basename(f.name)))
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
def make_sources_list(files):
|
|
Packit |
517ee8 |
ret = ""
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
for (i, f) in enumerate(files):
|
|
Packit |
517ee8 |
ret += "Source%i: %s\n" % (i, os.path.basename(f.name))
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return ret
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
def make_installer(scap_location, files):
|
|
Packit |
517ee8 |
prepper = ""
|
|
Packit |
517ee8 |
installer = ""
|
|
Packit |
517ee8 |
installed_files = ""
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
for (i, f) in enumerate(files):
|
|
Packit |
517ee8 |
prepper += "cp %%SOURCE%i .\n" % (i)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
installer += "cp %s $RPM_BUILD_ROOT/%s/%%{name}/\n" % (os.path.basename(f.name), scap_location)
|
|
Packit |
517ee8 |
installed_files += "%s/%%{name}/%s\n" % (scap_location, os.path.basename(f.name))
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return prepper, installer, installed_files
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
def create_spec(template_path, name,
|
|
Packit |
517ee8 |
version, release, summary, license,
|
|
Packit |
517ee8 |
scap_location, files,
|
|
Packit |
517ee8 |
target_file):
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
spec_template = """
|
|
Packit |
517ee8 |
# __ prefixed varibles in the form of ${__*} will get replaced by Python's string.Template
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
Name: ${__package_name}
|
|
Packit |
517ee8 |
Version: ${__package_version}
|
|
Packit |
517ee8 |
Release: ${__package_release}
|
|
Packit |
517ee8 |
Summary: ${__package_summary}
|
|
Packit |
517ee8 |
License: ${__package_license}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
${__package_sources}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
BuildArch: noarch
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
#BuildRequires: openscap-utils >= ${__package_openscap_version}
|
|
Packit |
517ee8 |
#Requires: openscap-utils >= ${__package_openscap_version}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
%description
|
|
Packit |
517ee8 |
This package was generated by scap-as-rpm.
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
%prep
|
|
Packit |
517ee8 |
${__package_prepper}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
%build
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
%install
|
|
Packit |
517ee8 |
mkdir -p $RPM_BUILD_ROOT/${__package_scap_location}/%{name}
|
|
Packit |
517ee8 |
${__package_installer}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
%files
|
|
Packit |
517ee8 |
${__package_installed_files}
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
%changelog
|
|
Packit |
517ee8 |
* ${__changelog_date} save-as-rpm - ${__package_version}-${__package_release}
|
|
Packit |
517ee8 |
- Autogenerated
|
|
Packit |
517ee8 |
"""
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
template = string.Template(spec_template)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
sources_list = make_sources_list(files)
|
|
Packit |
517ee8 |
prepper, installer, installed_files = make_installer(scap_location, files)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
spec_source = template.safe_substitute(
|
|
Packit |
517ee8 |
__package_name = name,
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
__package_version = version,
|
|
Packit |
517ee8 |
__package_release = release,
|
|
Packit |
517ee8 |
__package_summary = summary,
|
|
Packit |
517ee8 |
__package_license = license,
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
__package_scap_location = scap_location,
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
__package_sources = sources_list,
|
|
Packit |
517ee8 |
__package_openscap_version = "0.9.12", # FIXME
|
|
Packit |
517ee8 |
__package_prepper = prepper,
|
|
Packit |
517ee8 |
__package_installer = installer,
|
|
Packit |
517ee8 |
__package_installed_files = installed_files,
|
|
Packit |
517ee8 |
__changelog_date = datetime.date.today().strftime("%a %b %d %Y")
|
|
Packit |
517ee8 |
)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
target_file.write(spec_source)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
def main():
|
|
Packit |
517ee8 |
parser = argparse.ArgumentParser(
|
|
Packit |
517ee8 |
description = "Takes given SCAP input(s) and makes an RPM package that contains them. "
|
|
Packit |
517ee8 |
"The result RPM can be installed using # yum install ./package-name-1-1.rpm "
|
|
Packit |
517ee8 |
"which will put the contents into /usr/share/xml/scap. No dependency on openscap "
|
|
Packit |
517ee8 |
"or scap-workbench is enforced in the output package so you can use any "
|
|
Packit |
517ee8 |
"SCAP-capable scanner to evaluate the content.")
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
# we choose name automatically if its missing
|
|
Packit |
517ee8 |
parser.add_argument("--pkg-name", dest = "pkg_name", default = None,
|
|
Packit |
517ee8 |
help = "Name of the RPM package, if none is provided the basename of the first SCAP input is used. Ex.: xyz-security-guide")
|
|
Packit |
517ee8 |
parser.add_argument("--pkg-version", dest = "pkg_version", default = "1")
|
|
Packit |
517ee8 |
parser.add_argument("--pkg-release", dest = "pkg_release", default = "1")
|
|
Packit |
517ee8 |
parser.add_argument("--pkg-summary", dest = "pkg_summary", default = "stub",
|
|
Packit |
517ee8 |
help = "Optional short description of the package.")
|
|
Packit |
517ee8 |
parser.add_argument("--pkg-license", dest = "pkg_license", default = "Unknown",
|
|
Packit |
517ee8 |
help = "Short name of the license that you want to publish the package under. Ex.: GPLv2+, BSD, ...")
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
parser.add_argument("--pkg-scap-location", dest = "pkg_scap_location", default = "%{_datadir}/xml/scap",
|
|
Packit |
517ee8 |
help = "Folder where SCAP files are supposed to be installed. Each package will have its own folder "
|
|
Packit |
517ee8 |
"inside this folder. RPM variables can be used and will be expanded as usual. It is "
|
|
Packit |
517ee8 |
"recommended to keep the default settings.")
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
parser.add_argument("--rpm-destination", dest = "rpm_destination", default = ".",
|
|
Packit |
517ee8 |
help = "The folder (absolute or relative to CWD) where the result RPM shall be saved.")
|
|
Packit |
517ee8 |
parser.add_argument("--srpm-destination", dest = "srpm_destination", default = None,
|
|
Packit |
517ee8 |
help = "The folder (absolute or relative to CWD) where the result SRPM shall be saved.")
|
|
Packit |
517ee8 |
parser.add_argument("files", metavar = "FILE", nargs = "+",
|
|
Packit |
517ee8 |
help = "List of files that should be put into the result package. "
|
|
Packit |
517ee8 |
"These should be SCAP XML files but such requirement is not enforced.")
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
args = parser.parse_args()
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if not args.rpm_destination:
|
|
Packit |
517ee8 |
print("--rpm-destination has to be specified")
|
|
Packit |
517ee8 |
parser.print_help()
|
|
Packit |
517ee8 |
return 1
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if not os.path.isdir(args.rpm_destination):
|
|
Packit |
517ee8 |
print("'%s' does not seem like a directory or isn't accessible!" % args.rpm_destination)
|
|
Packit |
517ee8 |
parser.print_help()
|
|
Packit |
517ee8 |
return 1
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if args.srpm_destination is not None and not os.path.isdir(args.srpm_destination):
|
|
Packit |
517ee8 |
print("'%s' does not seem like a directory or isn't accessible!" % args.srpm_destination)
|
|
Packit |
517ee8 |
parser.print_help()
|
|
Packit |
517ee8 |
return 1
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
for fpath in args.files:
|
|
Packit |
517ee8 |
if not os.path.exists(fpath):
|
|
Packit |
517ee8 |
print("File '%s' does not exist or isn't accessible!" % fpath)
|
|
Packit |
517ee8 |
parser.print_help()
|
|
Packit |
517ee8 |
return 1
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
args.files = [open(fpath, "r") for fpath in args.files]
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
rpmbuild_sources_path, rpmbuild_rpm_path, rpmbuild_srpm_path = get_rpmbuild_paths()
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
copy_sources_to_rpmbuild(rpmbuild_sources_path, args.files)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
name = args.pkg_name
|
|
Packit |
517ee8 |
if name is None:
|
|
Packit |
517ee8 |
name, _ = os.path.splitext(os.path.basename(args.files[0].name))
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
temp_dir = tempfile.mkdtemp()
|
|
Packit |
517ee8 |
spec_file = open("%s/%s.spec" % (temp_dir, name), "w")
|
|
Packit |
517ee8 |
try:
|
|
Packit |
517ee8 |
create_spec("templates/package.spec",
|
|
Packit |
517ee8 |
name,
|
|
Packit |
517ee8 |
args.pkg_version, args.pkg_release, args.pkg_summary, args.pkg_license,
|
|
Packit |
517ee8 |
args.pkg_scap_location, args.files,
|
|
Packit |
517ee8 |
spec_file)
|
|
Packit |
517ee8 |
spec_file_path = spec_file.name
|
|
Packit |
517ee8 |
spec_file.close()
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
ret = subprocess.call(["rpmbuild", "-ba", spec_file_path], stdout = sys.stdout)
|
|
Packit |
517ee8 |
if ret != 0:
|
|
Packit |
517ee8 |
raise CannotContinueError("Failed to build RPM and SRPM for %s" % spec_file_path)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
finally:
|
|
Packit |
517ee8 |
shutil.rmtree(temp_dir)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
rpm_basename = "%s-%s-%s.noarch.rpm" % (name, args.pkg_version, args.pkg_release)
|
|
Packit |
517ee8 |
srpm_basename = "%s-%s-%s.src.rpm" % (name, args.pkg_version, args.pkg_release)
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
shutil.copy(os.path.join(rpmbuild_rpm_path, "noarch", rpm_basename), os.path.join(args.rpm_destination, rpm_basename))
|
|
Packit |
517ee8 |
if args.srpm_destination is not None:
|
|
Packit |
517ee8 |
shutil.copy(os.path.join(rpmbuild_srpm_path, srpm_basename), os.path.join(args.srpm_destination, srpm_basename))
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
print("")
|
|
Packit |
517ee8 |
print("Resulting RPM:\t'%s'" % (os.path.join(args.rpm_destination, rpm_basename)))
|
|
Packit |
517ee8 |
if args.srpm_destination is not None:
|
|
Packit |
517ee8 |
print("Resulting SRPM:\t'%s'" % (os.path.join(args.srpm_destination, srpm_basename)))
|
|
Packit |
517ee8 |
print("")
|
|
Packit |
517ee8 |
print("Finished!")
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
return 0
|
|
Packit |
517ee8 |
|
|
Packit |
517ee8 |
if __name__ == "__main__":
|
|
Packit |
517ee8 |
try:
|
|
Packit |
517ee8 |
ret = main()
|
|
Packit |
517ee8 |
sys.exit(ret)
|
|
Packit |
517ee8 |
except CannotContinueError as e:
|
|
Packit |
517ee8 |
sys.stderr.write("%s\n" % e.message)
|
|
Packit |
517ee8 |
sys.exit(1)
|