Ask Your Question
0

Heat: Using YAQL on SoftwareConfig Json Outputs

asked 2017-12-07 09:09:24 -0500

mathias gravatar image

updated 2017-12-07 09:47:51 -0500

Hi, my goal is to run scripts in my instances via software deployments that output the names of the network interfaces that connect to particular subnets. Here's the script:

#!/usr/bin/env python

import subprocess
import re
import os

p = subprocess.Popen(['ip', 'route', 'list'], stdout=subprocess.PIPE)
out, err = p.communicate()
lines = out.split('\n')

interfaces = []
for line in lines:
  if re.match("^[0-9./]* dev", line):
    tiles = line.split(" ")
    interfaces.append({'nic': tiles[2], 'cidr': tiles[0]})

result = {
  'interfaces': interfaces,
}

path = os.environ['heat_outputs_path'] + ".map"
file = open(path, "w")
file.write(str(result))
file.close()

The output looks somthing like

{
  'interfaces': [
    { 'nic': 'ens3', 'cidr': '192.168.0.0/24' },
    { 'nic': 'ens5', 'cidr': '192.168.1.0/24' }
  ]
}

Now I am trying to create an output for my Heat template that returns the name of the interface in the 192.168.0.0/24 network, so I expect the value of the output to be "ens3".

I haven't managed anything else yet but to have yaql return the entire data structure again :D

$ openstack stack output show test-nic-map --all
+-------+-----------------------------------------------------------------------------------+
| Field | Value                                                                             |
+-------+-----------------------------------------------------------------------------------+
| map   | {                                                                                 |
|       |   "output_value": "{'interfaces': [{'nic': 'ens3', 'cidr': '192.168.0.0/24'}]}",  |
|       |   "output_key": "map",                                                            |
|       |   "description": "No description given"                                           |
|       | }                                                                                 |
| nic   | {                                                                                 |
|       |   "output_value": "{'interfaces': [{'nic': 'ens3', 'cidr': '192.168.0.0/24'}]}",  |
|       |   "output_key": "nic",                                                            |
|       |   "description": "No description given"                                           |
|       | }                                                                                 |
+-------+-----------------------------------------------------------------------------------+

All other tries miserably failed. Can someone give me a hint how to do this?

outputs:

  nic:
    value:
      yaql:
        expression: "$.data"
        data: { get_attr: [ nic_map, map ] }

EDIT:

I just tried

outputs:

  nic:
    value:
      yaql:
        expression: "$.data.interfaces.where($.cidr = '192.168.0.0/24')"
        data: { get_attr: [ nic_map, map ] }

which fails with

$openstack stack output show test-nic-map --all
+-------+-----------------------------------------------------------------------------------+
| Field | Value                                                                             |
+-------+-----------------------------------------------------------------------------------+
| map   | {                                                                                 |
|       |   "output_value": "{'interfaces': [{'nic': 'ens3', 'cidr': '192.168.0.0/24'}]}",  |
|       |   "output_key": "map",                                                            |
|       |   "description": "No description given"                                           |
|       | }                                                                                 |
| nic   | {                                                                                 |
|       |   "output_value": null,                                                           |
|       |   "output_error": "Unknown function \"#property#interfaces\"",                    |
|       |   "output_key": "nic",                                                            |
|       |   "description": "No description given"                                           |
|       | }                                                                                 |
+-------+-----------------------------------------------------------------------------------+

I am getting the feeling I am using it wrong.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-12-07 10:40:07 -0500

zaneb gravatar image

updated 2017-12-08 09:08:29 -0500

The yaql expression for this would be:

$.data.interfaces.where($.cidr = "192.168.0.0/24").nic.first()

or

$.data.interfaces.where($.cidr = "192.168.0.0/24").select($.nic).first()

(BTW http://yaqluator.com/ is a handy way to try out different expressions.)

I wonder if the issue is that nothing is converting the JSON text back to Python objects (dicts/lists), and so yaql is just seeing the input as a string and therefore can't do anything much with it.

edit flag offensive delete link more

Comments

Your expression gives me an output_value of "null" and output_error is "u'interfaces'". It might be the case what your were suggesting last. A bug.

mathias gravatar imagemathias ( 2017-12-09 04:45:50 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Get to know Ask OpenStack

Resources for moderators

Question Tools

1 follower

Stats

Asked: 2017-12-07 09:09:24 -0500

Seen: 147 times

Last updated: Dec 08 '17