Merge "Implement podman rename via re-apply of containers"

This commit is contained in:
Zuul 2019-01-23 23:46:54 +00:00 committed by Gerrit Code Review
commit 6e82f649f1
2 changed files with 76 additions and 3 deletions

View File

@ -12,11 +12,13 @@
#
import collections
import jmespath
import json
import random
import string
import subprocess
from paunch.builder import podman
from paunch.utils import common
from paunch.utils import systemd
@ -157,6 +159,28 @@ class BaseRunner(object):
conf_id)
self.remove_containers(conf_id)
def discover_container_config(self, configs, container, name):
'''Find the paunch and runtime configs of a container by name.'''
for conf_id in self.current_config_ids():
jquerry = ("[] | [?(Name=='%s' && "
"Config.Labels.container_name=='%s' && "
"Config.Labels.config_id=='%s')]" %
(container, name, conf_id))
runtime_conf = None
try:
runtime_conf = jmespath.search(jquerry,
configs[conf_id])[0]
result = (conf_id, runtime_conf)
except Exception:
self.log.error("Failed searching container %s "
"for config %s" % (container, conf_id))
result = (None, None)
if runtime_conf:
self.log.debug("Found container %s "
"for config %s" % (container, conf_id))
break
return result
def list_configs(self):
configs = collections.defaultdict(list)
for conf_id in self.current_config_ids():
@ -259,6 +283,54 @@ class PodmanRunner(BaseRunner):
def rename_container(self, container, name):
# TODO(emilien) podman doesn't support rename, we'll handle it
# in paunch itself, probably.
self.log.warning("container renaming isn't supported by podman")
pass
# in paunch itself for now
configs = self.list_configs()
config_id, config = self.discover_container_config(
configs, container, name)
# Get config_data dict by the discovered conf ID,
# paunch needs it for maintaining idempotency within a conf ID
filter_names = ("[] | [?(Name!='%s' && "
"Config.Labels.config_id=='%s')]"
".Name" % (container, config_id))
filter_cdata = ("[] | [?(Name!='%s' && "
"Config.Labels.config_id=='%s')]"
".Config.Labels.config_data" % (container, config_id))
names = None
cdata = None
try:
names = jmespath.search(filter_names, configs[config_id])
cdata = jmespath.search(filter_cdata, configs[config_id])
except jmespath.exceptions.LexerError:
self.log.error("Failed to rename a container %s into %s: "
"used a bad search pattern" % (container, name))
return
if not names or not cdata:
self.log.error("Failed to rename a container %s into %s: "
"no config_data was found" % (container, name))
return
# Rename the wanted container in the config_data fetched from the
# discovered config
config_data = dict(zip(names, map(json.loads, cdata)))
config_data[name] = json.loads(
config.get('Config').get('Labels').get('config_data'))
# Re-apply a container under its amended name using the fetched configs
self.log.debug("Renaming a container known as %s into %s, "
"via re-applying its original config" %
(container, name))
self.log.debug("Removing the destination container %s" % name)
self.stop_container(name)
self.remove_container(name)
self.log.debug("Removing a container known as %s" % container)
self.stop_container(container)
self.remove_container(container)
builder = podman.PodmanBuilder(
config_id=config_id,
config=config_data,
runner=self,
labels=None,
log=self.log
)
builder.apply()

View File

@ -6,3 +6,4 @@ pbr>=2.0.0,!=2.1.0 # Apache-2.0
cliff>=2.6.0 # Apache-2.0
tenacity>=3.2.1 # Apache-2.0
jmespath>=0.9.0 # MIT