Skip to content

Commit

Permalink
Update registry schema semantics per review
Browse files Browse the repository at this point in the history
Example

<registry source="registry.suse.com">
    <containers backend="podman">
        <container name="some" tag="latest" path="some/path"/>
        <container name="some_other" fetch_only="true"/>
    </containers>
</registry>
  • Loading branch information
schaefi committed Oct 16, 2024
1 parent f7bf346 commit 3624270
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 78 deletions.
2 changes: 1 addition & 1 deletion kiwi/builder/template/container_import.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2024 SUSE Software Solutions Germany GmbH. All rights reserved.
# Copyright (c) 2024 SUSE LLC. All rights reserved.
#
# This file is part of kiwi.
#
Expand Down
25 changes: 19 additions & 6 deletions kiwi/schema/kiwi.rnc
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,23 @@ div {
k.registry =
element registry {
k.registry.attlist,
k.container+
k.containers+
}
}

#==========================================
# common element <containers>
#
div {
k.containers.backend.attribute =
## Use container with specified container backend
attribute backend { "podman" | "docker" }
k.containers.attlist =
k.containers.backend.attribute
k.containers =
element containers {
k.containers.attlist,
k.container*
}
}

Expand All @@ -1085,18 +1101,15 @@ div {
## Only fetch the container but do not activate the
## loading of the container at first boot
attribute fetch_only { xsd:boolean }
k.container.use_with.attribute =
## Use container with specified container backend
attribute use_with { "podman" | "docker" }
k.container.attlist =
k.container.name.attribute &
k.container.use_with.attribute &
k.container.tag.attribute? &
k.container.path.attribute? &
k.container.fetch_only.attribute?
k.container =
element container {
k.container.attlist
k.container.attlist,
empty
}
}

Expand Down
40 changes: 29 additions & 11 deletions kiwi/schema/kiwi.rng
Original file line number Diff line number Diff line change
Expand Up @@ -1636,11 +1636,38 @@ definition can be composed by other existing profiles.</a:documentation>
<element name="registry">
<ref name="k.registry.attlist"/>
<oneOrMore>
<ref name="k.container"/>
<ref name="k.containers"/>
</oneOrMore>
</element>
</define>
</div>
<!--
==========================================
common element <containers>
-->
<div>
<define name="k.containers.backend.attribute">
<attribute name="backend">
<a:documentation>Use container with specified container backend</a:documentation>
<choice>
<value>podman</value>
<value>docker</value>
</choice>
</attribute>
</define>
<define name="k.containers.attlist">
<ref name="k.containers.backend.attribute"/>
</define>
<define name="k.containers">
<element name="containers">
<ref name="k.containers.attlist"/>
<zeroOrMore>
<ref name="k.container"/>
</zeroOrMore>
</element>
</define>
</div>
<!--
==========================================
common element <container>
Expand Down Expand Up @@ -1669,19 +1696,9 @@ loading of the container at first boot</a:documentation>
<data type="boolean"/>
</attribute>
</define>
<define name="k.container.use_with.attribute">
<attribute name="use_with">
<a:documentation>Use container with specified container backend</a:documentation>
<choice>
<value>podman</value>
<value>docker</value>
</choice>
</attribute>
</define>
<define name="k.container.attlist">
<interleave>
<ref name="k.container.name.attribute"/>
<ref name="k.container.use_with.attribute"/>
<optional>
<ref name="k.container.tag.attribute"/>
</optional>
Expand All @@ -1696,6 +1713,7 @@ loading of the container at first boot</a:documentation>
<define name="k.container">
<element name="container">
<ref name="k.container.attlist"/>
<empty/>
</element>
</define>
</div>
Expand Down
129 changes: 104 additions & 25 deletions kiwi/xml_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2458,15 +2458,15 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
class registry(GeneratedsSuper):
subclass = None
superclass = None
def __init__(self, profiles=None, arch=None, source=None, container=None):
def __init__(self, profiles=None, arch=None, source=None, containers=None):
self.original_tagname_ = None
self.profiles = _cast(None, profiles)
self.arch = _cast(None, arch)
self.source = _cast(None, source)
if container is None:
self.container = []
if containers is None:
self.containers = []
else:
self.container = container
self.containers = containers
def factory(*args_, **kwargs_):
if CurrentSubclassModule_ is not None:
subclass = getSubclassFromModule_(
Expand All @@ -2478,11 +2478,11 @@ def factory(*args_, **kwargs_):
else:
return registry(*args_, **kwargs_)
factory = staticmethod(factory)
def get_container(self): return self.container
def set_container(self, container): self.container = container
def add_container(self, value): self.container.append(value)
def insert_container_at(self, index, value): self.container.insert(index, value)
def replace_container_at(self, index, value): self.container[index] = value
def get_containers(self): return self.containers
def set_containers(self, containers): self.containers = containers
def add_containers(self, value): self.containers.append(value)
def insert_containers_at(self, index, value): self.containers.insert(index, value)
def replace_containers_at(self, index, value): self.containers[index] = value
def get_profiles(self): return self.profiles
def set_profiles(self, profiles): self.profiles = profiles
def get_arch(self): return self.arch
Expand All @@ -2498,7 +2498,7 @@ def validate_arch_name(self, value):
validate_arch_name_patterns_ = [['^.*$']]
def hasContent_(self):
if (
self.container
self.containers
):
return True
else:
Expand Down Expand Up @@ -2539,8 +2539,8 @@ def exportChildren(self, outfile, level, namespaceprefix_='', name_='registry',
eol_ = '\n'
else:
eol_ = ''
for container_ in self.container:
container_.export(outfile, level, namespaceprefix_, name_='container', pretty_print=pretty_print)
for containers_ in self.containers:
containers_.export(outfile, level, namespaceprefix_, name_='containers', pretty_print=pretty_print)
def build(self, node):
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
Expand All @@ -2563,22 +2563,110 @@ def buildAttributes(self, node, attrs, already_processed):
if value is not None and 'source' not in already_processed:
already_processed.add('source')
self.source = value
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'containers':
obj_ = containers.factory()
obj_.build(child_)
self.containers.append(obj_)
obj_.original_tagname_ = 'containers'
# end class registry


class containers(GeneratedsSuper):
subclass = None
superclass = None
def __init__(self, backend=None, container=None):
self.original_tagname_ = None
self.backend = _cast(None, backend)
if container is None:
self.container = []
else:
self.container = container
def factory(*args_, **kwargs_):
if CurrentSubclassModule_ is not None:
subclass = getSubclassFromModule_(
CurrentSubclassModule_, containers)
if subclass is not None:
return subclass(*args_, **kwargs_)
if containers.subclass:
return containers.subclass(*args_, **kwargs_)
else:
return containers(*args_, **kwargs_)
factory = staticmethod(factory)
def get_container(self): return self.container
def set_container(self, container): self.container = container
def add_container(self, value): self.container.append(value)
def insert_container_at(self, index, value): self.container.insert(index, value)
def replace_container_at(self, index, value): self.container[index] = value
def get_backend(self): return self.backend
def set_backend(self, backend): self.backend = backend
def hasContent_(self):
if (
self.container
):
return True
else:
return False
def export(self, outfile, level, namespaceprefix_='', name_='containers', namespacedef_='', pretty_print=True):
imported_ns_def_ = GenerateDSNamespaceDefs_.get('containers')
if imported_ns_def_ is not None:
namespacedef_ = imported_ns_def_
if pretty_print:
eol_ = '\n'
else:
eol_ = ''
if self.original_tagname_ is not None:
name_ = self.original_tagname_
showIndent(outfile, level, pretty_print)
outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
already_processed = set()
self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='containers')
if self.hasContent_():
outfile.write('>%s' % (eol_, ))
self.exportChildren(outfile, level + 1, namespaceprefix_='', name_='containers', pretty_print=pretty_print)
showIndent(outfile, level, pretty_print)
outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
else:
outfile.write('/>%s' % (eol_, ))
def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='containers'):
if self.backend is not None and 'backend' not in already_processed:
already_processed.add('backend')
outfile.write(' backend=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.backend), input_name='backend')), ))
def exportChildren(self, outfile, level, namespaceprefix_='', name_='containers', fromsubclass_=False, pretty_print=True):
if pretty_print:
eol_ = '\n'
else:
eol_ = ''
for container_ in self.container:
container_.export(outfile, level, namespaceprefix_, name_='container', pretty_print=pretty_print)
def build(self, node):
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
self.buildChildren(child, node, nodeName_)
return self
def buildAttributes(self, node, attrs, already_processed):
value = find_attr_value_('backend', node)
if value is not None and 'backend' not in already_processed:
already_processed.add('backend')
self.backend = value
self.backend = ' '.join(self.backend.split())
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'container':
obj_ = container.factory()
obj_.build(child_)
self.container.append(obj_)
obj_.original_tagname_ = 'container'
# end class registry
# end class containers


class container(GeneratedsSuper):
subclass = None
superclass = None
def __init__(self, name=None, use_with=None, tag=None, path=None, fetch_only=None):
def __init__(self, name=None, tag=None, path=None, fetch_only=None):
self.original_tagname_ = None
self.name = _cast(None, name)
self.use_with = _cast(None, use_with)
self.tag = _cast(None, tag)
self.path = _cast(None, path)
self.fetch_only = _cast(bool, fetch_only)
Expand All @@ -2595,8 +2683,6 @@ def factory(*args_, **kwargs_):
factory = staticmethod(factory)
def get_name(self): return self.name
def set_name(self, name): self.name = name
def get_use_with(self): return self.use_with
def set_use_with(self, use_with): self.use_with = use_with
def get_tag(self): return self.tag
def set_tag(self, tag): self.tag = tag
def get_path(self): return self.path
Expand Down Expand Up @@ -2634,9 +2720,6 @@ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='
if self.name is not None and 'name' not in already_processed:
already_processed.add('name')
outfile.write(' name=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.name), input_name='name')), ))
if self.use_with is not None and 'use_with' not in already_processed:
already_processed.add('use_with')
outfile.write(' use_with=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.use_with), input_name='use_with')), ))
if self.tag is not None and 'tag' not in already_processed:
already_processed.add('tag')
outfile.write(' tag=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.tag), input_name='tag')), ))
Expand All @@ -2660,11 +2743,6 @@ def buildAttributes(self, node, attrs, already_processed):
if value is not None and 'name' not in already_processed:
already_processed.add('name')
self.name = value
value = find_attr_value_('use_with', node)
if value is not None and 'use_with' not in already_processed:
already_processed.add('use_with')
self.use_with = value
self.use_with = ' '.join(self.use_with.split())
value = find_attr_value_('tag', node)
if value is not None and 'tag' not in already_processed:
already_processed.add('tag')
Expand Down Expand Up @@ -9850,6 +9928,7 @@ def main():
"configoption",
"container",
"containerconfig",
"containers",
"description",
"dracut",
"drivers",
Expand Down
Loading

0 comments on commit 3624270

Please sign in to comment.