Skip to content

Commit

Permalink
Configure add_yum_repo_by_url plugin.
Browse files Browse the repository at this point in the history
* Place-holder configuration for plugin in prod and
  prod-without-koji inner templates.
* New yum_repourls keyword argument for OSBS.create_*_build, passed as
* parameter to BuildRequest.
* New DockJsonManipulator.dock_json_has_plugin_conf method.
* New dj property for BuildRequest for DockJsonManipulator, used in
  CommonBuild to set plugin configuration from yum_repourls parameter
  if such configuration is present.
* Validate yum_repourls parameter in CommonSpec.
* Test case for the above.
* New CLI argument for build, --add-yum-repo URI.
  • Loading branch information
twaugh committed May 6, 2015
1 parent 9449333 commit 3f9f87b
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 13 deletions.
6 changes: 6 additions & 0 deletions inputs/prod-without-koji_inner.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
},
"name": "distgit_fetch_artefacts"
},
{
"args": {
"repourls": []
},
"name": "add_yum_repo_by_url"
},
{
"name": "inject_yum_repo"
},
Expand Down
6 changes: 6 additions & 0 deletions inputs/prod_inner.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
},
"name": "koji"
},
{
"args": {
"repourls": []
},
"name": "add_yum_repo_by_url"
},
{
"name": "inject_yum_repo"
},
Expand Down
11 changes: 8 additions & 3 deletions osbs/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ def create_build_from_buildrequest(self, build_request, namespace=DEFAULT_NAMESP
return build_response

@osbsapi
def create_prod_build(self, git_uri, git_ref, user, component, target, architecture, namespace=DEFAULT_NAMESPACE):
def create_prod_build(self, git_uri, git_ref, user, component, target, architecture, yum_repourls=None,
namespace=DEFAULT_NAMESPACE):
build_request = self.get_build_request(PROD_BUILD_TYPE)
build_request.set_params(
git_uri=git_uri,
Expand All @@ -118,6 +119,7 @@ def create_prod_build(self, git_uri, git_ref, user, component, target, architect
vendor=self.build_conf.get_vendor(),
build_host=self.build_conf.get_build_host(),
authoritative_registry=self.build_conf.get_authoritative_registry(),
yum_repourls=yum_repourls,
metadata_plugin_use_auth=self.build_conf.get_metadata_plugin_use_auth(),
)
build_json = build_request.render()
Expand All @@ -127,7 +129,7 @@ def create_prod_build(self, git_uri, git_ref, user, component, target, architect
return build_response

@osbsapi
def create_prod_without_koji_build(self, git_uri, git_ref, user, component, architecture,
def create_prod_without_koji_build(self, git_uri, git_ref, user, component, architecture, yum_repourls=None,
namespace=DEFAULT_NAMESPACE):
build_request = self.get_build_request(PROD_WITHOUT_KOJI_BUILD_TYPE)
build_request.set_params(
Expand All @@ -142,6 +144,7 @@ def create_prod_without_koji_build(self, git_uri, git_ref, user, component, arch
vendor=self.build_conf.get_vendor(),
build_host=self.build_conf.get_build_host(),
authoritative_registry=self.build_conf.get_authoritative_registry(),
yum_repourls=yum_repourls,
metadata_plugin_use_auth=self.build_conf.get_metadata_plugin_use_auth(),
)
build_json = build_request.render()
Expand All @@ -150,7 +153,8 @@ def create_prod_without_koji_build(self, git_uri, git_ref, user, component, arch
return build_response

@osbsapi
def create_simple_build(self, git_uri, git_ref, user, component, namespace=DEFAULT_NAMESPACE):
def create_simple_build(self, git_uri, git_ref, user, component, yum_repourls=None,
namespace=DEFAULT_NAMESPACE):
build_request = self.get_build_request(SIMPLE_BUILD_TYPE)
build_request.set_params(
git_uri=git_uri,
Expand All @@ -159,6 +163,7 @@ def create_simple_build(self, git_uri, git_ref, user, component, namespace=DEFAU
component=component,
registry_uri=self.build_conf.get_registry_uri(),
openshift_uri=self.os_conf.get_openshift_api_uri(),
yum_repourls=yum_repourls,
)
build_json = build_request.render()
response = self.os.create_build(json.dumps(build_json), namespace=namespace)
Expand Down
12 changes: 12 additions & 0 deletions osbs/build/build_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(self, build_json_store):
self.build_json = None # rendered template
self._template = None # template loaded from filesystem
self._inner_template = None # dock json
self._dj = None

def set_params(self, **kwargs):
"""
Expand Down Expand Up @@ -96,6 +97,12 @@ def inner_template(self):
self._inner_template = json.load(fp)
return self._inner_template

@property
def dj(self):
if self._dj is None:
self._dj = DockJsonManipulator(self.template, self.inner_template)
return self._dj


class CommonBuild(BuildRequest):
def __init__(self, build_json_store):
Expand All @@ -117,6 +124,7 @@ def set_params(self, **kwargs):
:param user: str, user part of resulting image name
:param component: str, component part of the image name
:param openshift_uri: str, URL of openshift instance for the build
:param yum_repourls: list of str, URLs to yum repo files to include
"""
logger.debug("setting params '%s' for %s", kwargs, self.spec)
self.spec.set_params(**kwargs)
Expand All @@ -127,6 +135,10 @@ def render(self):
self.template['parameters']['source']['git']['uri'] = self.spec.git_uri.value
self.template['parameters']['source']['git']['ref'] = self.spec.git_ref.value
self.template['parameters']['output']['registry'] = self.spec.registry_uri.value
if (self.spec.yum_repourls.value is not None and
self.dj.dock_json_has_plugin_conf('prebuild_plugins', "add_yum_repo_by_url")):
self.dj.dock_json_set_arg('prebuild_plugins', "add_yum_repo_by_url", "repourls",
self.spec.yum_repourls.value)

def validate_input(self):
self.spec.validate()
Expand Down
34 changes: 27 additions & 7 deletions osbs/build/manipulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,42 @@ def get_dock_json(self):
dock_json = json.loads(dock_json_str)
return dock_json

def _dock_json_get_plugin_conf(self, plugin_type, plugin_name):
def dock_json_get_plugin_conf(self, plugin_type, plugin_name):
"""
Return the configuration for a plugin.
Raises KeyError if there are no plugins of that type.
Raises IndexError if the named plugin is not listed.
"""
match = [x for x in self.dock_json[plugin_type] if x.get('name', None) == plugin_name]
return match[0]

def dock_json_has_plugin_conf(self, plugin_type, plugin_name):
"""
Check whether a plugin is configured.
"""

try:
match = [x for x in self.dock_json[plugin_type] if x.get('name', None) == plugin_name]
self.dock_json_get_plugin_conf(plugin_type, plugin_name)
return True
except (KeyError, IndexError):
return False

def _dock_json_get_plugin_conf_or_fail(self, plugin_type, plugin_name):
try:
conf = self.dock_json_get_plugin_conf(plugin_type, plugin_name)
except KeyError:
raise RuntimeError("Invalid dock json: plugin type '%s' misses" % plugin_type)
if len(match) <= 0:
except IndexError:
raise RuntimeError("no such plugin in dock json: \"%s\"" % plugin_name)
return match[0]
return conf

def dock_json_set_arg(self, plugin_type, plugin_name, arg_key, arg_value):
plugin_conf = self._dock_json_get_plugin_conf(plugin_type, plugin_name)
plugin_conf = self._dock_json_get_plugin_conf_or_fail(plugin_type, plugin_name)
plugin_conf['args'][arg_key] = arg_value

def dock_json_merge_arg(self, plugin_type, plugin_name, arg_key, arg_dict):
plugin_conf = self._dock_json_get_plugin_conf(plugin_type, plugin_name)
plugin_conf = self._dock_json_get_plugin_conf_or_fail(plugin_type, plugin_name)

# Values supplied by the caller override those from the template JSON
template_value = plugin_conf['args'].get(arg_key, {})
Expand All @@ -61,4 +82,3 @@ def write_dock_json(self):
if len(p) <= 0:
raise RuntimeError("\"env\" misses key DOCK_PLUGINS")
p[0]['value'] = json.dumps(self.dock_json)

6 changes: 5 additions & 1 deletion osbs/build/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class CommonSpec(BuildTypeSpec):
registry_uri = BuildParam('registry_uri')
openshift_uri = BuildParam('openshift_uri')
name = BuildParam("name")
yum_repourls = BuildParam("yum_repourls")

def __init__(self):
self.required_params = [
Expand All @@ -93,13 +94,16 @@ def __init__(self):
]

def set_params(self, git_uri=None, git_ref=None, registry_uri=None, user=None,
component=None, openshift_uri=None, **kwargs):
component=None, openshift_uri=None, yum_repourls=None, **kwargs):
self.git_uri.value = git_uri
self.git_ref.value = git_ref
self.user.value = user
self.component.value = component
self.registry_uri.value = registry_uri
self.openshift_uri.value = openshift_uri
if not (yum_repourls is None or isinstance(yum_repourls, list)):
raise OsbsValidationException("yum_repourls must be a list")
self.yum_repourls.value = yum_repourls or []
d = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
self.name.value = "%s-%s" % (self.component.value, d)

Expand Down
5 changes: 4 additions & 1 deletion osbs/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def cmd_build(args, osbs):
component=args.component,
target=args.target,
architecture=args.arch,
namespace=args.namespace
yum_repourls=args.add_yum_repo,
namespace=args.namespace,
)
build_id = build.build_id
if not args.no_logs:
Expand Down Expand Up @@ -246,6 +247,8 @@ def cli():
help="name of component")
build_parser.add_argument("--no-logs", action='store_true', required=False, default=False,
help="don't print logs after submitting build")
build_parser.add_argument("--add-yum-repo", action='append', metavar="URL",
help="URL of yum repo file")
build_parser.set_defaults(func=cmd_build)

parser.add_argument("--openshift-uri", action='store', metavar="URL",
Expand Down
59 changes: 58 additions & 1 deletion tests/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from osbs.build.manipulate import DockJsonManipulator
from osbs.build.build_request import BuildManager
from osbs.constants import BUILD_FINISHED_STATES, PROD_BUILD_TYPE, PROD_WITHOUT_KOJI_BUILD_TYPE
from osbs.exceptions import OsbsValidationException
from tests.constants import TEST_BUILD, TEST_LABEL, TEST_LABEL_VALUE


Expand Down Expand Up @@ -314,6 +315,60 @@ def test_render_prod_without_koji_request():
assert labels['Vendor'] is not None


def test_render_with_yum_repourls():
this_file = inspect.getfile(test_render_prod_request)
this_dir = os.path.dirname(this_file)
parent_dir = os.path.dirname(this_dir)
inputs_path = os.path.join(parent_dir, "inputs")
bm = BuildManager(inputs_path)
kwargs = {
'git_uri': "http://git/",
'git_ref': "master",
'user': "john-foo",
'component': "component",
'registry_uri': "registry.example.com",
'openshift_uri': "http://openshift/",
'koji_target': "koji-target",
'kojiroot': "http://root/",
'kojihub': "http://hub/",
'sources_command': "make",
'architecture': "x86_64",
'vendor': "Foo Vendor",
'build_host': "our.build.host.example.com",
'authoritative_registry': "registry.example.com",
}
build_request = bm.get_build_request_by_type("prod")

# Test validation for yum_repourls parameter
kwargs['yum_repourls'] = 'should be a list'
with pytest.raises(OsbsValidationException):
build_request.set_params(**kwargs)

# Use a valid yum_repourls parameter and check the result
kwargs['yum_repourls'] = ['http://example.com/repo1.repo',
'http://example.com/repo2.repo']
build_request.set_params(**kwargs)
build_json = build_request.render()
strategy = build_json['parameters']['strategy']['customStrategy']['env']
plugins_json = None
for d in strategy:
if d['name'] == 'DOCK_PLUGINS':
plugins_json = d['value']
break

assert plugins_json is not None
plugins = json.loads(plugins_json)

repourls = None
for d in plugins['prebuild_plugins']:
if d['name'] == 'add_yum_repo_by_url':
repourls = d['args']['repourls']

assert repourls is not None
assert len(repourls) == 2
assert 'http://example.com/repo1.repo' in repourls
assert 'http://example.com/repo2.repo' in repourls

def test_get_user(openshift):
l = openshift.get_user()
assert l.json() is not None
Expand All @@ -327,4 +382,6 @@ def test_watch_build(openshift):

def test_create_build(openshift):
response = openshift.create_build({})
assert response is not None
assert response is not None
assert response.json()["metadata"]["name"] == TEST_BUILD
assert response.json()["status"].lower() in BUILD_FINISHED_STATES

0 comments on commit 3f9f87b

Please sign in to comment.