Merge "Fall back to regexes in kolla_toolbox with Docker API 1.24"
This commit is contained in:
commit
3ace7f93b3
@ -14,8 +14,10 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from distutils.version import StrictVersion
|
||||||
import docker
|
import docker
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
@ -89,6 +91,13 @@ EXAMPLES = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
JSON_REG = re.compile('^(?P<host>\w+) \| (?P<status>\w+)!? =>(?P<stdout>.*)$',
|
||||||
|
re.MULTILINE | re.DOTALL)
|
||||||
|
NON_JSON_REG = re.compile(('^(?P<host>\w+) \| (?P<status>\w+)!? \| '
|
||||||
|
'rc=(?P<exit_code>\d+) >>\n(?P<stdout>.*)\n$'),
|
||||||
|
re.MULTILINE | re.DOTALL)
|
||||||
|
|
||||||
|
|
||||||
def gen_commandline(params):
|
def gen_commandline(params):
|
||||||
command = ['ansible', 'localhost']
|
command = ['ansible', 'localhost']
|
||||||
if params.get('module_name'):
|
if params.get('module_name'):
|
||||||
@ -111,6 +120,11 @@ def get_docker_client():
|
|||||||
return docker.APIClient
|
return docker.APIClient
|
||||||
|
|
||||||
|
|
||||||
|
def docker_supports_environment_in_exec(client):
|
||||||
|
docker_version = StrictVersion(client.api_version)
|
||||||
|
return docker_version >= StrictVersion('1.25')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
specs = dict(
|
specs = dict(
|
||||||
module_name=dict(required=True, type='str'),
|
module_name=dict(required=True, type='str'),
|
||||||
@ -130,43 +144,79 @@ def main():
|
|||||||
module.fail_json(msg='kolla_toolbox container is not running.')
|
module.fail_json(msg='kolla_toolbox container is not running.')
|
||||||
|
|
||||||
kolla_toolbox = kolla_toolbox[0]
|
kolla_toolbox = kolla_toolbox[0]
|
||||||
# Use the JSON output formatter, so that we can parse it.
|
|
||||||
environment = {"ANSIBLE_STDOUT_CALLBACK": "json",
|
|
||||||
"ANSIBLE_LOAD_CALLBACK_PLUGINS": "True"}
|
|
||||||
job = client.exec_create(kolla_toolbox, command_line,
|
|
||||||
environment=environment)
|
|
||||||
json_output = client.exec_start(job)
|
|
||||||
|
|
||||||
try:
|
# NOTE(mgoddard): Docker 1.12 has API version 1.24, and was installed by
|
||||||
output = json.loads(json_output)
|
# kolla-ansible bootstrap-servers on Rocky and earlier releases. This API
|
||||||
except Exception as e:
|
# version does not have support for specifying environment variables for
|
||||||
module.fail_json(
|
# exec jobs, which is necessary to use the Ansible JSON output formatter.
|
||||||
msg='Can not parse the inner module output: %s' % json_output)
|
# While we continue to support this version of Docker, fall back to the old
|
||||||
|
# regex-based method for API version 1.24 and earlier.
|
||||||
|
# TODO(mgoddard): Remove this conditional (keep the if) when we require
|
||||||
|
# Docker API version 1.25+.
|
||||||
|
if docker_supports_environment_in_exec(client):
|
||||||
|
# Use the JSON output formatter, so that we can parse it.
|
||||||
|
environment = {"ANSIBLE_STDOUT_CALLBACK": "json",
|
||||||
|
"ANSIBLE_LOAD_CALLBACK_PLUGINS": "True"}
|
||||||
|
job = client.exec_create(kolla_toolbox, command_line,
|
||||||
|
environment=environment)
|
||||||
|
json_output = client.exec_start(job)
|
||||||
|
|
||||||
# Expected format is the following:
|
try:
|
||||||
# {
|
output = json.loads(json_output)
|
||||||
# "plays": [
|
except Exception as e:
|
||||||
# {
|
module.fail_json(
|
||||||
# "tasks": [
|
msg='Can not parse the inner module output: %s' % json_output)
|
||||||
# {
|
|
||||||
# "hosts": {
|
|
||||||
# "localhost": {
|
|
||||||
# <module result>
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# ]
|
|
||||||
# {
|
|
||||||
# ]
|
|
||||||
# }
|
|
||||||
try:
|
|
||||||
ret = output['plays'][0]['tasks'][0]['hosts']['localhost']
|
|
||||||
except (KeyError, IndexError) as e:
|
|
||||||
module.fail_json(
|
|
||||||
msg='Ansible JSON output has unexpected format: %s' % output)
|
|
||||||
|
|
||||||
# Remove Ansible's internal variables from returned fields.
|
# Expected format is the following:
|
||||||
ret.pop('_ansible_no_log', None)
|
# {
|
||||||
|
# "plays": [
|
||||||
|
# {
|
||||||
|
# "tasks": [
|
||||||
|
# {
|
||||||
|
# "hosts": {
|
||||||
|
# "localhost": {
|
||||||
|
# <module result>
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# {
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
try:
|
||||||
|
ret = output['plays'][0]['tasks'][0]['hosts']['localhost']
|
||||||
|
except (KeyError, IndexError) as e:
|
||||||
|
module.fail_json(
|
||||||
|
msg='Ansible JSON output has unexpected format: %s' % output)
|
||||||
|
|
||||||
|
# Remove Ansible's internal variables from returned fields.
|
||||||
|
ret.pop('_ansible_no_log', None)
|
||||||
|
else:
|
||||||
|
job = client.exec_create(kolla_toolbox, command_line)
|
||||||
|
output = client.exec_start(job)
|
||||||
|
|
||||||
|
for exp in [JSON_REG, NON_JSON_REG]:
|
||||||
|
m = exp.match(output)
|
||||||
|
if m:
|
||||||
|
inner_output = m.groupdict().get('stdout')
|
||||||
|
status = m.groupdict().get('status')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
module.fail_json(
|
||||||
|
msg='Can not parse the inner module output: %s' % output)
|
||||||
|
|
||||||
|
ret = dict()
|
||||||
|
try:
|
||||||
|
ret = json.loads(inner_output)
|
||||||
|
except ValueError:
|
||||||
|
# Some modules (e.g. command) do not produce a JSON output.
|
||||||
|
# Instead, check the status, and assume changed on success.
|
||||||
|
ret['stdout'] = inner_output
|
||||||
|
if status != "SUCCESS":
|
||||||
|
ret['failed'] = True
|
||||||
|
else:
|
||||||
|
# No way to know whether changed - assume yes.
|
||||||
|
ret['changed'] = True
|
||||||
|
|
||||||
module.exit_json(**ret)
|
module.exit_json(**ret)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user