ca7d6256e5
Instead of multiple places handling the same thing duplicating the logic, it's better to do it once upfront. This allows easy caching of the results. Additional advantage of this approach is that the config dump will include resolved URLs. The original reference will still be available in the copy of the original config. JIRA: COMPOSE-3065 Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
168 lines
4.9 KiB
Python
Executable File
168 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
import kobo.conf
|
|
import six
|
|
|
|
here = sys.path[0]
|
|
if here != '/usr/bin':
|
|
# Git checkout
|
|
sys.path[0] = os.path.dirname(here)
|
|
|
|
import pungi.checks
|
|
import pungi.compose
|
|
import pungi.paths
|
|
import pungi.phases
|
|
import pungi.wrappers.scm
|
|
import pungi.util
|
|
from pungi.wrappers.variants import VariantsXmlParser, VariantsValidationError
|
|
|
|
|
|
class ValidationCompose(pungi.compose.Compose):
|
|
def __init__(self, conf, has_old, topdir):
|
|
self.topdir = topdir
|
|
self.conf = conf
|
|
self._logger = None
|
|
self.just_phases = []
|
|
self.skip_phases = []
|
|
self.has_old_composes = has_old
|
|
self.paths = pungi.paths.Paths(self)
|
|
self.variants = {}
|
|
|
|
@property
|
|
def old_composes(self):
|
|
return '/dummy' if self.has_old_composes else None
|
|
|
|
@property
|
|
def compose_id(self):
|
|
return 'Dummy-1.0-20160811.t.0'
|
|
|
|
@property
|
|
def compose_type(self):
|
|
return 'test'
|
|
|
|
@property
|
|
def compose_date(self):
|
|
return '20160811'
|
|
|
|
@property
|
|
def compose_respin(self):
|
|
return '0'
|
|
|
|
|
|
def read_variants(compose, config):
|
|
with pungi.util.temp_dir() as tmp_dir:
|
|
scm_dict = compose.conf["variants_file"]
|
|
if isinstance(scm_dict, six.string_types) and scm_dict[0] != '/':
|
|
config_dir = os.path.dirname(config)
|
|
scm_dict = os.path.join(config_dir, scm_dict)
|
|
files = pungi.wrappers.scm.get_file_from_scm(scm_dict, tmp_dir)
|
|
tree_arches = compose.conf.get("tree_arches")
|
|
tree_variants = compose.conf.get("tree_variants")
|
|
with open(os.path.join(tmp_dir, files[0]), "r") as file_obj:
|
|
parser = VariantsXmlParser(file_obj, tree_arches, tree_variants)
|
|
compose.variants = parser.parse()
|
|
|
|
compose.all_variants = {}
|
|
for variant in compose.variants.values():
|
|
compose.all_variants[variant.uid] = variant
|
|
for child in variant.get_variants():
|
|
compose.all_variants[child.uid] = child
|
|
|
|
|
|
def run(config, topdir, has_old, offline):
|
|
conf = kobo.conf.PyConfigParser()
|
|
conf.load_from_file(config)
|
|
|
|
errors, warnings = pungi.checks.validate(conf, offline=offline)
|
|
if errors or warnings:
|
|
for error in errors + warnings:
|
|
print(error)
|
|
sys.exit(1)
|
|
|
|
errors = []
|
|
compose = ValidationCompose(conf, has_old, topdir)
|
|
try:
|
|
read_variants(compose, config)
|
|
except VariantsValidationError as exc:
|
|
errors.extend(str(exc).splitlines())
|
|
except:
|
|
# Failed to read variants, no big deal.
|
|
pass
|
|
|
|
pkgset_phase = pungi.phases.PkgsetPhase(compose)
|
|
buildinstall_phase = pungi.phases.BuildinstallPhase(compose)
|
|
phases = [
|
|
pungi.phases.InitPhase(compose),
|
|
buildinstall_phase,
|
|
pkgset_phase,
|
|
pungi.phases.GatherPhase(compose, pkgset_phase),
|
|
pungi.phases.ExtraFilesPhase(compose, pkgset_phase),
|
|
pungi.phases.CreaterepoPhase(compose),
|
|
pungi.phases.OstreeInstallerPhase(compose, buildinstall_phase),
|
|
pungi.phases.OSTreePhase(compose),
|
|
pungi.phases.ProductimgPhase(compose, pkgset_phase),
|
|
pungi.phases.CreateisoPhase(compose, buildinstall_phase),
|
|
pungi.phases.ExtraIsosPhase(compose),
|
|
pungi.phases.LiveImagesPhase(compose),
|
|
pungi.phases.LiveMediaPhase(compose),
|
|
pungi.phases.ImageBuildPhase(compose),
|
|
pungi.phases.ImageChecksumPhase(compose),
|
|
pungi.phases.TestPhase(compose),
|
|
]
|
|
|
|
for phase in phases:
|
|
if phase.skip():
|
|
continue
|
|
try:
|
|
phase.validate()
|
|
except ValueError as ex:
|
|
for i in str(ex).splitlines():
|
|
errors.append("%s: %s" % (phase.name.upper(), i))
|
|
|
|
return errors
|
|
|
|
|
|
class DumpSchemaAction(argparse.Action):
|
|
def __call__(self, parser, ns, values, option_string=None):
|
|
json.dump(pungi.checks.make_schema(), sys.stdout,
|
|
sort_keys=True, indent=4)
|
|
print('')
|
|
sys.exit(0)
|
|
|
|
|
|
def main(args=None):
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--dump-schema', nargs=0, action=DumpSchemaAction,
|
|
help='print JSON Schema of configuration and exit')
|
|
parser.add_argument('config', metavar='CONFIG',
|
|
help='configuration file to validate')
|
|
parser.add_argument('--old-composes', action='store_true',
|
|
help='indicate if pungi-koji will be run with --old-composes option')
|
|
parser.add_argument(
|
|
"--offline",
|
|
action="store_true",
|
|
help="Do not validate git references in URLs",
|
|
)
|
|
opts = parser.parse_args(args)
|
|
|
|
with pungi.util.temp_dir() as topdir:
|
|
errors = run(opts.config, topdir, opts.old_composes, opts.offline)
|
|
|
|
for msg in errors:
|
|
print(msg)
|
|
|
|
return bool(errors)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if main():
|
|
sys.exit(1)
|