Merge pull request #70 from salt-formulas/andrewp-fix-relative-classes

fix relative class names
diff --git a/reclass/core.py b/reclass/core.py
index 66c74f5..75eea54 100644
--- a/reclass/core.py
+++ b/reclass/core.py
@@ -123,10 +123,6 @@
                     except ResolveError as e:
                         raise ClassNameResolveError(klass, nodename, entity.uri)
 
-            # for convenience, first level classes_uri/class.yml can have un-interpolated "."
-            if klass.startswith('.'):
-                klass = klass[1:]
-
             if klass not in seen:
                 try:
                     class_entity = self._storage.get_class(klass, environment, self._settings)
diff --git a/reclass/storage/yaml_fs/__init__.py b/reclass/storage/yaml_fs/__init__.py
index 7540aa4..20e8eec 100644
--- a/reclass/storage/yaml_fs/__init__.py
+++ b/reclass/storage/yaml_fs/__init__.py
@@ -96,7 +96,6 @@
         try:
             relpath = self._nodes[name]
             path = os.path.join(self.nodes_uri, relpath)
-            name = os.path.splitext(relpath)[0]
         except KeyError as e:
             raise reclass.errors.NodeNotFound(self.name, name, self.nodes_uri)
         entity = YamlData.from_file(path).get_entity(name, settings)
@@ -108,13 +107,7 @@
             path = os.path.join(self.classes_uri, self._classes[name])
         except KeyError as e:
             raise reclass.errors.ClassNotFound(self.name, name, self.classes_uri)
-
-        if path.endswith('init{}'.format(FILE_EXTENSION)):
-            parent_class=name
-        else:
-            # for regular class yml file, strip its name
-            parent_class='.'.join(name.split('.')[:-1])
-        entity = YamlData.from_file(path).get_entity(name, settings, parent_class)
+        entity = YamlData.from_file(path).get_entity(name, settings)
         return entity
 
     def enumerate_nodes(self):
diff --git a/reclass/storage/yaml_git/__init__.py b/reclass/storage/yaml_git/__init__.py
index 61c4551..45cb6c0 100644
--- a/reclass/storage/yaml_git/__init__.py
+++ b/reclass/storage/yaml_git/__init__.py
@@ -258,15 +258,7 @@
             raise reclass.errors.NotFoundError("File " + name + " missing from " + uri.repo + " branch " + uri.branch)
         file = self._repos[uri.repo].files[uri.branch][name]
         blob = self._repos[uri.repo].get(file.id)
-
-        if file.name.endswith('init{}'.format(FILE_EXTENSION)):
-            parent_class=name
-        else:
-            # for regular class yml file, strip its name
-            parent_class='.'.join(name.split('.')[:-1])
-
-        entity = YamlData.from_string(blob.data, 'git_fs://{0} {1} {2}'.format(uri.repo, uri.branch,
-            file.path)).get_entity(name, settings, parent_class)
+        entity = YamlData.from_string(blob.data, 'git_fs://{0} {1} {2}'.format(uri.repo, uri.branch, file.path)).get_entity(name, settings)
         return entity
 
     def enumerate_nodes(self):
diff --git a/reclass/storage/yamldata.py b/reclass/storage/yamldata.py
index 52547ac..034832d 100644
--- a/reclass/storage/yamldata.py
+++ b/reclass/storage/yamldata.py
@@ -53,16 +53,26 @@
     def get_data(self):
         return self._data
 
-    def get_entity(self, name, settings, parent_class=None):
+    def set_absolute_names(self, name, names):
+        parent = '.'.join(name.split('.')[0:-1])
+        new_names = []
+        for n in names:
+            if n[0] == '.':
+                if parent == '':
+                    n = n[1:]
+                else:
+                    n = parent + n
+            new_names.append(n)
+        return new_names
+
+    def get_entity(self, name, settings):
         #if name is None:
         #    name = self._uri
 
         classes = self._data.get('classes')
         if classes is None:
             classes = []
-        if parent_class:
-            classes = \
-                [parent_class + c for c in classes if c.startswith('.')]
+        classes = self.set_absolute_names(name, classes)
         classes = datatypes.Classes(classes)
 
         applications = self._data.get('applications')
diff --git a/reclass/tests/data/02/classes/one/alpha.yml b/reclass/tests/data/02/classes/one/alpha.yml
new file mode 100644
index 0000000..a13cc5c
--- /dev/null
+++ b/reclass/tests/data/02/classes/one/alpha.yml
@@ -0,0 +1,7 @@
+classes:
+- .beta
+- two.beta
+
+parameters:
+  test1: ${one_beta}
+  test2: ${two_beta}
diff --git a/reclass/tests/data/02/classes/one/beta.yml b/reclass/tests/data/02/classes/one/beta.yml
new file mode 100644
index 0000000..f754252
--- /dev/null
+++ b/reclass/tests/data/02/classes/one/beta.yml
@@ -0,0 +1,2 @@
+parameters:
+  one_beta: 1
diff --git a/reclass/tests/data/02/classes/three.yml b/reclass/tests/data/02/classes/three.yml
new file mode 100644
index 0000000..987fde0
--- /dev/null
+++ b/reclass/tests/data/02/classes/three.yml
@@ -0,0 +1,2 @@
+classes:
+- .one.alpha
diff --git a/reclass/tests/data/02/classes/two/beta.yml b/reclass/tests/data/02/classes/two/beta.yml
new file mode 100644
index 0000000..1f578b2
--- /dev/null
+++ b/reclass/tests/data/02/classes/two/beta.yml
@@ -0,0 +1,2 @@
+parameters:
+  two_beta: 2
diff --git a/reclass/tests/data/02/nodes/relative.yml b/reclass/tests/data/02/nodes/relative.yml
new file mode 100644
index 0000000..1f2bbdc
--- /dev/null
+++ b/reclass/tests/data/02/nodes/relative.yml
@@ -0,0 +1,2 @@
+classes:
+  - one.alpha
diff --git a/reclass/tests/data/02/nodes/top_relative.yml b/reclass/tests/data/02/nodes/top_relative.yml
new file mode 100644
index 0000000..5dae5be
--- /dev/null
+++ b/reclass/tests/data/02/nodes/top_relative.yml
@@ -0,0 +1,2 @@
+classes:
+  - three
diff --git a/reclass/tests/data/03/classes/a.yml b/reclass/tests/data/03/classes/a.yml
new file mode 100644
index 0000000..748a297
--- /dev/null
+++ b/reclass/tests/data/03/classes/a.yml
@@ -0,0 +1,6 @@
+parameters:
+  a: 1
+  alpha:
+  - ${a}
+  beta:
+    a: ${a}
diff --git a/reclass/tests/data/03/classes/b.yml b/reclass/tests/data/03/classes/b.yml
new file mode 100644
index 0000000..cce2609
--- /dev/null
+++ b/reclass/tests/data/03/classes/b.yml
@@ -0,0 +1,6 @@
+parameters:
+  b: 2
+  alpha:
+  - ${b}
+  beta:
+    b: ${b}
diff --git a/reclass/tests/data/03/classes/c.yml b/reclass/tests/data/03/classes/c.yml
new file mode 100644
index 0000000..7441417
--- /dev/null
+++ b/reclass/tests/data/03/classes/c.yml
@@ -0,0 +1,6 @@
+parameters:
+  c: 3
+  alpha:
+  - ${c}
+  beta:
+    c: ${c}
diff --git a/reclass/tests/data/03/classes/d.yml b/reclass/tests/data/03/classes/d.yml
new file mode 100644
index 0000000..e61a1ff
--- /dev/null
+++ b/reclass/tests/data/03/classes/d.yml
@@ -0,0 +1,6 @@
+parameters:
+  d: 4
+  alpha:
+  - ${d}
+  beta:
+    d: ${d}
diff --git a/reclass/tests/data/03/nodes/alpha/one.yml b/reclass/tests/data/03/nodes/alpha/one.yml
new file mode 100644
index 0000000..f2b613d
--- /dev/null
+++ b/reclass/tests/data/03/nodes/alpha/one.yml
@@ -0,0 +1,3 @@
+classes:
+- a
+- b
diff --git a/reclass/tests/data/03/nodes/alpha/two.yml b/reclass/tests/data/03/nodes/alpha/two.yml
new file mode 100644
index 0000000..b020af3
--- /dev/null
+++ b/reclass/tests/data/03/nodes/alpha/two.yml
@@ -0,0 +1,3 @@
+classes:
+- a
+- c
diff --git a/reclass/tests/data/03/nodes/beta/one.yml b/reclass/tests/data/03/nodes/beta/one.yml
new file mode 100644
index 0000000..168a4fb
--- /dev/null
+++ b/reclass/tests/data/03/nodes/beta/one.yml
@@ -0,0 +1,3 @@
+classes:
+- b
+- c
diff --git a/reclass/tests/data/03/nodes/beta/two.yml b/reclass/tests/data/03/nodes/beta/two.yml
new file mode 100644
index 0000000..56c6343
--- /dev/null
+++ b/reclass/tests/data/03/nodes/beta/two.yml
@@ -0,0 +1,3 @@
+classes:
+- c
+- d
diff --git a/reclass/tests/test_core.py b/reclass/tests/test_core.py
index 047bf24..ced18e8 100644
--- a/reclass/tests/test_core.py
+++ b/reclass/tests/test_core.py
@@ -59,6 +59,33 @@
         params = { 'node_test': 'class not found', '_reclass_': { 'environment': 'base', 'name': {'full': 'class_notfound', 'short': 'class_notfound' } } }
         self.assertEqual(node['parameters'], params)
 
+    def test_relative_class_names(self):
+        reclass = self._core('02')
+        node = reclass.nodeinfo('relative')
+        params = { 'test1': 1, 'test2': 2, 'one_beta': 1, 'two_beta': 2, '_reclass_': { 'environment': 'base', 'name': { 'full': 'relative', 'short': 'relative' } } }
+        self.assertEqual(node['parameters'], params)
+
+    def test_top_relative_class_names(self):
+        reclass = self._core('02')
+        node = reclass.nodeinfo('top_relative')
+        params = { 'test1': 1, 'test2': 2, 'one_beta': 1, 'two_beta': 2, '_reclass_': { 'environment': 'base', 'name': { 'full': 'top_relative', 'short': 'top_relative' } } }
+        self.assertEqual(node['parameters'], params)
+
+    def test_compose_node_names(self):
+        reclass = self._core('03', {'compose_node_name': True})
+        alpha_one_node = reclass.nodeinfo('alpha.one')
+        alpha_one_res = {'a': 1, 'alpha': [1, 2], 'beta': {'a': 1, 'b': 2}, 'b': 2, '_reclass_': {'environment': 'base', 'name': {'full': 'alpha.one', 'short': 'alpha'}}}
+        alpha_two_node = reclass.nodeinfo('alpha.two')
+        alpha_two_res = {'a': 1, 'alpha': [1, 3], 'beta': {'a': 1, 'c': 3}, 'c': 3, '_reclass_': {'environment': 'base', 'name': {'full': 'alpha.two', 'short': 'alpha'}}}
+        beta_one_node = reclass.nodeinfo('beta.one')
+        beta_one_res = {'alpha': [2, 3], 'beta': {'c': 3, 'b': 2}, 'b': 2, 'c': 3, '_reclass_': {'environment': 'base', 'name': {'full': 'beta.one', 'short': 'beta'}}}
+        beta_two_node = reclass.nodeinfo('beta.two')
+        beta_two_res = {'alpha': [3, 4], 'c': 3, 'beta': {'c': 3, 'd': 4}, 'd': 4, '_reclass_': {'environment': u'base', 'name': {'full': u'beta.two', 'short': u'beta'}}}
+        self.assertEqual(alpha_one_node['parameters'], alpha_one_res)
+        self.assertEqual(alpha_two_node['parameters'], alpha_two_res)
+        self.assertEqual(beta_one_node['parameters'], beta_one_res)
+        self.assertEqual(beta_two_node['parameters'], beta_two_res)
+
 
 if __name__ == '__main__':
     unittest.main()