4 #----------------------------------------------------------------------------------
6 # Copyright (c) 2021 AT&T Intellectual Property.
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
20 #---------------------------------------------------------------------------------
23 # Abstract: A config file (json) parser that looks for one or more "descriptions" and outputs
24 # shell styled variable assignments that can be sourced by a script. Descriptions
26 # <field>:[<field>:...:{*|shell_var_name}
28 # The description "xapp_name:*" will find the field xapp_name at the top level
29 # and generate the variable assignment using the field name. The description
30 # "xapp_name:xname" would find the same field but generate "xname=value" in the
33 # It may be necssary to pull a field from an array of objects where a second field
34 # in the object has a desired value. As an example, in the messaging section there
35 # is an expected array of ports with each port having a name. To exctact a field
36 # like this, the final field in the list may have the form:
37 # <name>[]<match_name>=<desired-value>@<field-name>
39 # For "messaging:port[]name=rmr-data@port"
40 # The messaging object is first located, and each element in the port array is examined.
41 # when the element which contains the field "name:, with a value of "rmr-data",
42 # the value of "port" is assigned to the output shell variable name.
44 # Limitations: This only allows one array to be traversed, and it is assumed to be the
45 # last field. In other words, nested object arrays are not supported.
47 # Usage: j2src <config-file-name> <description> [<description>...]
49 # Date: 29 Janurary 2021
50 # Author: E. Scott Daniels
51 # ------------------------------------------------------------------------------------------------------
55 # Parse the description (see above) and return name and value to the caller. None,None is returned
56 # when we have an error, or cannot find the field. Debug strings MUST start with # so that they don't
57 # affect shell parsing of output.
59 def parse( pj, description, debug=False ) :
60 tokens = description.split( ":" ) # split fields, last is the output name or *
64 if len( tokens ) < 2 :
65 print( "## ERR ## badly formed description: %s" % description )
68 for i in range( len( tokens ) - 1 ) :
69 atoks = tokens[i].split( "[]" )
70 if len( atoks ) > 1 : # array; [0] is the name, [1] is name=value@desired-name
72 nv = atoks[1].split( "=" )
74 sv = nv[1].split( "@" )
77 print( "## ERR ## badly formed capture string: missing 'value<desired'" )
85 ao = pj[atoks[0]] # directly at the array object
86 for i in range( len( ao ) ) : # run each element
88 if ao[i][name] == match_val : # this is the one we want
89 if pull_name in ao[i] :
90 return out_name, str( ao[i][pull_name] ) # all things go back as string
93 print( "## WRN ## field is not in, or match value %s does NOT match, in %s[%d]: %s" % ( match_val, atoks[0], i, ao[i][name] ) )
95 return None, None # nothing matched and returned; bail now; array must be last field
99 print( "## WRN ## array %s is not found in %s" % (atoks[0], tokens[i]) )
103 pj = pj[atoks[0]] # if not last, this will be an object (we hope)
105 value = pj # last one should just be a field to yank
108 print( "## WRN ## field not found: %s" % atoks[0] )
114 return out_name, value
117 # take the name, value and print it as a valid shell variable. We convert True/False or true/false to
120 def print_svar( vname, value ) :
121 if value == "True" or value == "true" :
123 if value == "False" or value == "false" :
125 if not value.isnumeric() :
126 value = '"' + value + '"'
128 vname = vname.replace( " ", "_" ) # ensure it's a valid shell variable name
129 vname = vname.replace( "-", "_" )
131 print( "%s=%s" % ( vname, value ) )
135 # --------------------------------------------------------------------------------------------------------------
139 if sys.argv[1] == "debug" :
143 f = open( sys.argv[aidx] )
148 for i in range( aidx, len( sys.argv ) ) :
149 name, val = parse( pj, sys.argv[i], debug )
151 if name != None and val != None :
152 print_svar( name, val )