0

All,

Background: I have a customer who has some build scripts for their datacenter based on python that I've inherited. I did not work on the original design so I'm sort of limited to some degree on what I can and can't change. That said, my customer has a properties file that they use in their datacenter. Some of the values are used to build their servers and unfortunately they have other applications that also use these values so I cannot change them to make it easier for me.

What I want to do is make the scripts more dynamic to distribute more hosts so that I don't have to keep updating the scripts in the future and can just add more hosts to the property file. Unfortunately I can't change the current property file and have to work with it.

The property file looks something like this:

projectName.ClusterNameServer1.sslport=443

projectName.ClusterNameServer1.port=80

projectName.ClusterNameServer1.host=myHostA

projectName.ClusterNameServer2.sslport=443

projectName.ClusterNameServer2.port=80

projectName.ClusterNameServer2.host=myHostB

In their deployment scripts they basically have alot of if projectName.ClusterNameServerX where X is some number of entries defined and then do something, e.g.:

if projectName.ClusterNameServer1.host != "" do X

if projectName.ClusterNameServer2.host != "" do X

if projectName.ClusterNameServer3.host != "" do X

Then when they add another host (say Serve4) they've added another if statement.

Question: What I would like to do is make the scripts more dynamic and parse the properties file and put what I need into some data structure to pass to the deployment scripts and then just iterate over the structure and do my deployment that way so I don't have to constantly add a bunch of if some host# do something. I'm just curious to feed some suggestions as to what others would do to parse the file and what sort of data structure would they use and how they would group things together by ClusterNameServer# or something else.

Thanks

1
  • what is the 'do something'? is it the same for all hosts or different? Commented Mar 17, 2011 at 20:11

3 Answers 3

3
  1. Create a sqlite database to represent the data in the properties file.

  2. Write a script to dump the data from the properties file into the sqlite database.

  3. Write a script that can regenerate the properties file based on the data in the sqlite database. New hosts can now be added by inserting rows into the sqlite database. Every time an update or insert is done, run this script to keep the old scripts happy, until step 5 is completed.

  4. Have all new scripts interact with the sqlite database instead of the properties file.

  5. Rewrite the old scripts to use the sqlite database. For example, looping through results from sql queries instead of adding more if statements.

Sign up to request clarification or add additional context in comments.

8 Comments

very nice, I doubt 5 will be possible in the case described, but sounds great.
@BiggAl If you can't rewrite old scripts in order to make them able to receive or to internaly create the needed data, I don't understand how you will reach your aim.
Some of the values are used to build their servers and unfortunately they have other applications that also use these values so I cannot change them to make it easier for me. Not my question though...
@BiggAl When I read "I doubt 5 will be possible" , I understood that "Rewrite the old scripts" isn't possible. In fact , you wanted to say that "sql queries instead of adding more if statements" isn't possible, I think. You wrote : "I can't change the current property file" , OK for this. But you did write also : "What I want to do is make the scripts more dynamic" : I understand it's about the "build scripts" and that you can rewrite some limited part or add a snippet to them. If you want to pass a data structure, you must make the "build scripts" able to receive it, no ?
@BiggAl I understood that you can't change the content of the "property file" , but that you wanted to change the manner to extract the data from it. If it isn't what you try to do, please give clearer explanations.
|
1

Since your property names have some internal structure to them, you might try using pyparsing to process your properties file:

from pyparsing import Word, alphas, alphanums, delimitedList, restOfLine

props = """
projectName.ClusterNameServer1.sslport=443
projectName.ClusterNameServer1.port=80
projectName.ClusterNameServer1.host=myHostA
projectName.ClusterNameServer2.sslport=443
projectName.ClusterNameServer2.port=80
projectName.ClusterNameServer2.host=myHostB
"""

# define format of a single property definition line
ident = Word(alphas, alphanums+'_')
propertyName = delimitedList(ident,'.')
propertyDefn = propertyName("name") + '=' + restOfLine("value")

# sample code that parses the properties and accesses the
# name and value fields
for prop in propertyDefn.searchString(props):
    print '.'.join(prop.name), '->', prop.value

Prints:

projectName.ClusterNameServer1.sslport -> 443
projectName.ClusterNameServer1.port -> 80
projectName.ClusterNameServer1.host -> myHostA
projectName.ClusterNameServer2.sslport -> 443
projectName.ClusterNameServer2.port -> 80
projectName.ClusterNameServer2.host -> myHostB

If you can rely on the project-server-parameter structure of the properties, you can build a hierarchical object using defaultdicts (from the collections module):

# use defaultdicts to accumulate these values into a nested structure
from collections import defaultdict
properties = defaultdict(lambda:defaultdict(dict))

# build hierarchical property structure
# (assumes very rigid project-server-parameter naming)
for prop in propertyDefn.searchString(props):
    properties[prop.name[0]][prop.name[1]][prop.name[2]] = prop.value

# show data in nice outline form
for project in properties:
    print '-', project
    for cluster in properties[project]:
        print '  -', cluster
        for param in properties[project][cluster]:
            print '    -', param, properties[project][cluster][param]

Prints:

- projectName
  - ClusterNameServer1
    - host myHostA
    - sslport 443
    - port 80
  - ClusterNameServer2
    - host myHostB
    - sslport 443
    - port 80

Comments

0

Executing the following code creates a dictionnary whose keys are server's number and values are (sslport,port,host)

import re

RE = ('projectName.ClusterNameServer(\d+)\.sslport=(\d+)\s+'
      'projectName.ClusterNameServer\\1\.port=(\d+)\s+'
      'projectName.ClusterNameServer\\1\.host=(\S+)(?:\s+|\Z)')

propertyfile_name = 'servers.txt'

with open(propertyfile_name) as f:
    dico = dict( (server,(s,p,h)) for (server,s,p,h) in re.findall(RE,f.read()) )

print dico

result

dico== {'1': ('443', '80', 'myHostA'), '2': ('443', '80', 'myHostB')}

Then the dico data can be passed " to the deployment scripts "; I don't know what are your possibilities to pass this data. It may be done as a flat file, or, better, a pickle file.

The simplest solution would be to include the lines of the above code directly into the "deployment scripts" so as they would have the data without the need to receive the data from outside.

. EDIT

Another solution, that I find better:

import csv
from itertools import ifilter

propertyfile_name = 'servers.txt'

with open(propertyfile_name,'rb') as f:
    dico = dict( ifilter(None,csv.reader(f,delimiter='=')) )    
print dico

The ifilter() function is necessary because of blank lines in the file.

result

{'projectName.ClusterNameServer2.host': 'myHostB', 'projectName.ClusterNameServer2.port': '80', 'projectName.ClusterNameServer1.host': 'myHostA', 'projectName.ClusterNameServer1.port': '80', 'projectName.ClusterNameServer2.sslport': '443', 'projectName.ClusterNameServer1.sslport': '443'}

.

EDIT

RE = ('(projectName.ClusterNameServer\d+\.(?:sslport|port|host))=(\S+)(?:\s+|\Z)')

propertyfile_name = 'servers.txt'

with open(propertyfile_name) as f:
    dico = dict( re.findall(RE,f.read()) )

print dico

Same result

If you want result

dico== {'1': ('443', '80', 'myHostA'), '2': ('443', '80', 'myHostB')}

I will do tomorrow

2 Comments

thanks for the suggestions. Another question on the re module example. Is it possible to group "like properties" together even though they may not be ordered like in the example.
@user275633 I edited to answer. What do you call 'to group' , in fact ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.