aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NOTES39
-rw-r--r--steuermann/nodes.py44
-rw-r--r--steuermann/specfile.exy44
3 files changed, 116 insertions, 11 deletions
diff --git a/NOTES b/NOTES
index e830812..88bf2fe 100644
--- a/NOTES
+++ b/NOTES
@@ -60,3 +60,42 @@ There are bunches of other details that I'll have to describe some time.
Mark
+--------------------
+
+The new HOSTGROUP feature works like this:
+
+# defines a set of conditions - each condition is a python function in a CONDITIONS block
+CONDITIONS
+ def foo() :
+ return True
+ def bar() :
+ return False
+END
+# the END must be on a line by itself
+
+
+HOSTGROUP @xyz
+ IF foo : a1 a2 a3
+ # adds a1, a2, a3 to hostgroup @xyz if condition foo() returns trun
+ IF bar : b1 b2 b3
+ # adds b1, b2, b3 to hostgroup @xyz if condition bar() returns trun
+
+
+TABLE whatever HOST @xyz banana
+ # defines table whatever to be on all the hosts in xyz and the host banana
+ ...
+
+hostgroup is implemented up to here.
+
+The following feature is not implemented yet:
+
+ AFTER @xyz:this/that
+
+is the same as
+ AFTER a1:this/that
+ AFTER a2:this/that
+ AFTER a3:this/that
+
+assuming that condition foo() was true and bar() was false
+
+
diff --git a/steuermann/nodes.py b/steuermann/nodes.py
index 3ad4639..4264a64 100644
--- a/steuermann/nodes.py
+++ b/steuermann/nodes.py
@@ -351,6 +351,50 @@ def read_file_list( file_list ) :
di.finish()
return di
+#####
+
+saved_conditions = { }
+
+def declare_conditions( text, filename ) :
+ # the parameter "text" is the token that begins "CONDITION\n"
+ # and ends "\nEND\n", with a block of python code in the middle.
+ #
+ # the parameter "filename" is what file we were processing when
+ # we saw this set of conditions defined.
+
+ # process the junk off the ends of the text
+ text = text.split('\n',1)[1] # tear off "CONDITION\n"
+ text = text.rsplit('\n',2)[0] # tear off "END\n"
+
+ # if it is indented at all, compensate for the indent so the
+ # exec will work
+ if text.startswith(' ') or text.startswith('\t') :
+ text = 'if 1 :\n' + text
+
+ # exec it into the dict
+ exec text in saved_conditions
+
+def check_condition( name, filename ) :
+ if name in saved_conditions :
+ ans = saved_conditions[name]()
+ else :
+ ans = False
+ return ans
+
+#####
+
+hostgroups = { }
+
+def add_hostgroup( name, host ) :
+ if not name in hostgroups :
+ hostgroups[name] = [ ]
+ hostgroups[name].append(host)
+
+def get_hostgroup( name ) :
+ return hostgroups[name]
+
+#####
+
if __name__=='__main__':
import sys
n = read_file_list( sys.argv[1:] )
diff --git a/steuermann/specfile.exy b/steuermann/specfile.exy
index cb2aa36..00c7547 100644
--- a/steuermann/specfile.exy
+++ b/steuermann/specfile.exy
@@ -2,6 +2,7 @@
# Parse a Steuermann Spec file
#
# This is an exyapps grammer in specfile.exy
+import nodes
%%
parser specfile:
@@ -9,37 +10,58 @@ parser specfile:
ignore: "#.*\n"
token END: "$"
+ token HOSTGROUP: "HOSTGROUP"
+ token IF: "IF"
token TABLE: "TABLE"
token HOST : "HOST"
token CMD: "CMD"
token OPT: "OPT"
token AFTER: "AFTER"
+ token RUN: "RUN"
+ token LOCAL: "LOCAL"
+ token IMPORT: "IMPORT"
+ token DEBUG: "DEBUG"
token name: "[a-zA-Z0-9_.-]+"
token STAR: "\*"
token cmdname: "[a-zA-Z0-9_.-]+"
token tablename: "[a-zA-Z0-9_.-]+"
token wildname: "[*?a-zA-Z0-9_.-]+"
- token RUN: "RUN"
- token LOCAL: "LOCAL"
token string: '"[^"]*"'
token SLASH: "/"
token COLON: ":"
- token IMPORT: "IMPORT"
+ token hostgroup: "@[a-zA-Z0-9_.-]+"
+
+ # watch carefully: none of the keywords are "END" on a line by themselves
+ token CONDITIONS: 'CONDITIONS[^"]*\n[\s]*END[ \t]*\n'
rule start: table_list END {{ return table_list }}
- rule table_list: table_section [ table_list ]
+ rule table_list: table_section +
rule table_section:
- TABLE tablename {{ table_name = tablename }}
- HOST {{ hostlist = [ ] }}
- (
- name {{ hostlist.append(name) }}
- )+
+ DEBUG string {{ print "-->debug: %s"%string }}
+ | hostgroup_def
+ | CONDITIONS {{ nodes.declare_conditions( CONDITIONS, self._scanner.filename ) }}
+ | TABLE tablename {{ table_name = tablename }} HOST {{ hostlist = [ ] }}
+ (
+ name {{ hostlist.append(name) }}
+ | hostgroup {{ hostlist = hostlist + nodes.get_hostgroup( hostgroup ) }}
+ )+
command_list
- # command_list is a list of (command, pos) where command is the text from the file and pos is the location in the file
+ # command_list is a list of (command, pos) where command is the text from the file and pos is the location in the file
{{ self.data.add_command_list( table_name, hostlist, command_list ) }}
- | IMPORT string {{ self.data.import_list.append( string[1:-1] ) }}
+ | IMPORT string {{ self.data.import_list.append( string[1:-1] ) }}
+
+ ##
+ rule hostgroup_def :
+ HOSTGROUP hostgroup ( hostgroup_if<<hostgroup>> )+
+
+ rule hostgroup_if<<hg>> :
+ IF name
+ {{ accept_nodes = nodes.check_condition(name, self._scanner.filename ) }}
+ COLON (
+ name {{ if accept_nodes : nodes.add_hostgroup( hg, name ) }}
+ )+
rule command_list:
# one or more commands, appended together into a list