Merge "Implement podman rename via re-apply of containers"
This commit is contained in:
commit
6e82f649f1
|
@ -12,11 +12,13 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
import jmespath
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from paunch.builder import podman
|
||||||
from paunch.utils import common
|
from paunch.utils import common
|
||||||
from paunch.utils import systemd
|
from paunch.utils import systemd
|
||||||
|
|
||||||
|
@ -157,6 +159,28 @@ class BaseRunner(object):
|
||||||
conf_id)
|
conf_id)
|
||||||
self.remove_containers(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):
|
def list_configs(self):
|
||||||
configs = collections.defaultdict(list)
|
configs = collections.defaultdict(list)
|
||||||
for conf_id in self.current_config_ids():
|
for conf_id in self.current_config_ids():
|
||||||
|
@ -259,6 +283,54 @@ class PodmanRunner(BaseRunner):
|
||||||
|
|
||||||
def rename_container(self, container, name):
|
def rename_container(self, container, name):
|
||||||
# TODO(emilien) podman doesn't support rename, we'll handle it
|
# TODO(emilien) podman doesn't support rename, we'll handle it
|
||||||
# in paunch itself, probably.
|
# in paunch itself for now
|
||||||
self.log.warning("container renaming isn't supported by podman")
|
configs = self.list_configs()
|
||||||
pass
|
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()
|
||||||
|
|
|
@ -6,3 +6,4 @@ pbr>=2.0.0,!=2.1.0 # Apache-2.0
|
||||||
|
|
||||||
cliff>=2.6.0 # Apache-2.0
|
cliff>=2.6.0 # Apache-2.0
|
||||||
tenacity>=3.2.1 # Apache-2.0
|
tenacity>=3.2.1 # Apache-2.0
|
||||||
|
jmespath>=0.9.0 # MIT
|
||||||
|
|
Loading…
Reference in New Issue