node class inheritence

This commit is contained in:
dave 2018-10-14 22:44:22 -07:00
parent a5583d83d2
commit 00d05f2a55
6 changed files with 54 additions and 24 deletions

View File

@ -17,17 +17,20 @@ import ZODB.FileStorage
# print(v.conf) # print(v.conf)
# def main():
# storage = ZODB.FileStorage.FileStorage("pupper.db")
# db = ZODB.DB(storage)
# with db.transaction() as c:
# del c.root.nodes["puppettest5.scc.net.davepedu.com"].classes["base2"]
def main(): def main():
storage = ZODB.FileStorage.FileStorage("pupper.db") storage = ZODB.FileStorage.FileStorage("pupper.db")
db = ZODB.DB(storage) db = ZODB.DB(storage)
with db.transaction() as c: with db.transaction() as c:
print(c.root.nodes["puppettest5.scc.net.davepedu.com"].parents) for host in ("scc", "root", "puppettest5.scc.net.davepedu.com"):
if "foo2" in c.root.nodes[host].classes:
del c.root.nodes[host].classes["foo2"]
# del c.root.nodes["scc"].classes["foo2"]
# def main():
# storage = ZODB.FileStorage.FileStorage("pupper.db")
# db = ZODB.DB(storage)
# with db.transaction() as c:
# print(c.root.nodes["puppettest5.scc.net.davepedu.com"].parents)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,7 +1,6 @@
import os import os
import cherrypy import cherrypy
import logging import logging
from datetime import datetime, timedelta
from nodepupper.nodeops import NodeOps, NObject, NClass, NClassAttachment from nodepupper.nodeops import NodeOps, NObject, NClass, NClassAttachment
from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2 import Environment, FileSystemLoader, select_autoescape
from nodepupper.common import pwhash from nodepupper.common import pwhash
@ -35,6 +34,7 @@ def slugify(words):
return ''.join(letter for letter in '-'.join(words.lower().split()) return ''.join(letter for letter in '-'.join(words.lower().split())
if ('a' <= letter <= 'z') or ('0' <= letter <= '9') or letter == '-') if ('a' <= letter <= 'z') or ('0' <= letter <= '9') or letter == '-')
def recurse_params(node): def recurse_params(node):
params = yaml.load(node.body) params = yaml.load(node.body)
for item in node.parents: for item in node.parents:
@ -43,6 +43,16 @@ def recurse_params(node):
params[k] = v params[k] = v
return params return params
def recurse_classes(node):
classes = {c.cls: c.conf for _, c in node.classes.items()}
for item in node.parents:
for cls, conf in recurse_classes(item).items():
if cls not in classes:
classes[cls] = conf
return classes
class AppWeb(object): class AppWeb(object):
def __init__(self, nodedb, template_dir): def __init__(self, nodedb, template_dir):
self.nodes = nodedb self.nodes = nodedb
@ -75,12 +85,17 @@ class AppWeb(object):
return ret return ret
@cherrypy.expose @cherrypy.expose
def node_edit(self, node=None, op=None, body=None, fqdn=None): def node_edit(self, node=None, op=None, body=None, fqdn=None, parent=None):
if op in ("Edit", "Create") and body and fqdn: if op in ("Edit", "Create") and body and fqdn:
with self.nodes.db.transaction() as c: with self.nodes.db.transaction() as c:
obj = c.root.nodes[fqdn] if fqdn in c.root.nodes else NObject(fqdn, body) obj = c.root.nodes[fqdn] if fqdn in c.root.nodes else NObject(fqdn, body)
obj.body = body obj.body = body
obj.parents.clear()
parent = parent or []
for name in [parent] if isinstance(parent, str) else parent:
obj.parents.append(c.root.nodes[name])
c.root.nodes[fqdn] = obj c.root.nodes[fqdn] = obj
raise cherrypy.HTTPRedirect("node/{}".format(fqdn), 302) raise cherrypy.HTTPRedirect("node/{}".format(fqdn), 302)
with self.nodes.db.transaction() as c: with self.nodes.db.transaction() as c:
yield self.render("node_edit.html", node=c.root.nodes.get(node, None)) yield self.render("node_edit.html", node=c.root.nodes.get(node, None))
@ -94,12 +109,14 @@ class AppWeb(object):
# raise cherrypy.HTTPRedirect('feed', 302) # raise cherrypy.HTTPRedirect('feed', 302)
@cherrypy.expose @cherrypy.expose
def puppet(self, fqdn): def puppet(self, fqdn, preview=False):
with self.nodes.db.transaction() as c: with self.nodes.db.transaction() as c:
node = c.root.nodes[fqdn] node = c.root.nodes[fqdn]
doc = {"environment": "production", doc = {"environment": "production",
"classes": {k: yaml.load(v.conf) or {} for k, v in node.classes.items()}, "classes": {cls.name: yaml.load(conf) or {} for cls, conf in recurse_classes(node).items()},
"parameters": recurse_params(node)} "parameters": recurse_params(node)}
if preview:
yield "<plaintext>"
yield "---\n" yield "---\n"
yield yaml.dump(doc, default_flow_style=False) yield yaml.dump(doc, default_flow_style=False)
@ -131,7 +148,7 @@ class AppWeb(object):
@cherrypy.popargs("node") @cherrypy.popargs("node")
class NodesWeb(object): class NodesWeb(object):
def __init__(self, root): def __init__(self, root):
self.root = root # self.base = root
self.nodes = root.nodes self.nodes = root.nodes
self.render = root.render self.render = root.render

View File

@ -21,6 +21,9 @@ class NObject(persistent.Persistent):
self.classes = pmap() self.classes = pmap()
self.body = body self.body = body
def parent_names(self):
return [n.fqdn for n in self.parents]
class NClass(persistent.Persistent): class NClass(persistent.Persistent):
def __init__(self, name): def __init__(self, name):

View File

@ -8,7 +8,9 @@
<input type="submit" class="secondary-button pure-button" name="op" value="Make all private" /> <input type="submit" class="secondary-button pure-button" name="op" value="Make all private" />
<input type="submit" class="secondary-button pure-button" name="op" value="Delete tag" /> <input type="submit" class="secondary-button pure-button" name="op" value="Delete tag" />
</form>--> </form>-->
<a href="//node/{{ node.fqdn }}/attach"><button class="secondary-button pure-button">Attach class</button></a> <a href="/node_edit?node={{ node.fqdn }}"><button class="secondary-button pure-button">Edit</button></a>
<a href="/node/{{ node.fqdn }}/attach"><button class="secondary-button pure-button">Attach class</button></a>
<a href="/puppet?preview=true&fqdn={{ node.fqdn }}"><button class="secondary-button pure-button">Render</button></a>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
@ -24,7 +26,7 @@
<div class="node-parents"> <div class="node-parents">
<h2>Parents</h2> <h2>Parents</h2>
{% for item in node.parents %} {% for item in node.parents %}
{{ item.fqdn }} <br /> <a href="/node/{{ item.fqdn }}">{{ item.fqdn }}</a><br />
{% endfor %} {% endfor %}
</div> </div>
<div class="node-classes"> <div class="node-classes">
@ -37,6 +39,7 @@
<div class="class-conf"> <div class="class-conf">
<pre>{{ class.conf }}</pre> <pre>{{ class.conf }}</pre>
</div> </div>
<hr/>
{% endfor %} {% endfor %}
</div> </div>
<div class="node-add-class"> <div class="node-add-class">

View File

@ -20,6 +20,14 @@
<label for="offset">Offset (minutes)</label> <label for="offset">Offset (minutes)</label>
<input id="offset" class="pure-u-1-2" type="text" name="offset" value="xxx" /> <input id="offset" class="pure-u-1-2" type="text" name="offset" value="xxx" />
</div> --> </div> -->
<div class="pure-u-1">
<label for="parent">Parents</label>
<select multiple name="parent">
{% for item in nodenames %}{% if item != node.fqdn %}
<option value="{{ item }}"{% if node and item in node.parent_names() %} selected="selected"{% endif %}>{{ item }}</option>
{% endif %}{% endfor %}
</select>
</div>
<div class="pure-u-1"> <div class="pure-u-1">
<input type="submit" class="pure-button pure-button-primary" name="op" value="{% if node %}Edit{% else %}Create{% endif %}" /> <input type="submit" class="pure-button pure-button-primary" name="op" value="{% if node %}Edit{% else %}Create{% endif %}" />
</div> </div>

View File

@ -6,17 +6,13 @@
{% block body %} {% block body %}
<div class="nodes-all"> <div class="nodes-all">
{% for node in nodes %} <ul>
<div class="node"> {% for node in nodes|sort(attribute="fqdn") %}
<h2>{{ node.fqdn }}</h2> <li>
<p> <a href="/node/{{ node.fqdn }}">{{ node.fqdn }}</a>
<a href="/node/{{ node.fqdn }}">view</a> <a href="/node_edit?node={{ node.fqdn }}">edit</a> </li>
</p>
<pre>
{{ node.body }}
</pre>
</div>
{% endfor %} {% endfor %}
</ul>
</div> </div>
{% endblock %} {% endblock %}