Allow overriding node definitions created by repeat function

Change-Id: I50f2f6393a5e033f10ce4711bfda50c618d3733b
diff --git a/reclass/storage/node.sls b/reclass/storage/node.sls
index ed9a9f1..4870c9c 100644
--- a/reclass/storage/node.sls
+++ b/reclass/storage/node.sls
@@ -1,7 +1,8 @@
 {%- from "reclass/map.jinja" import storage with context %}
+
 {%- if storage.enabled %}
 
-{%- if storage.reclass_nodes_cleanup %}
+  {%- if storage.reclass_nodes_cleanup %}
 {{ storage.base_dir }}/nodes/_generated_cleanup:
   file.directory:
     - name: {{ storage.base_dir }}/nodes/_generated
@@ -11,47 +12,45 @@
     - file_mode: 644
     - makedirs: True
     - clean: True
-{%- endif %}
+  {%- endif %}
 
-{%- set storage_by_name = {} %}
+  {%- set storage_by_name = {} %}
 
-{%- for node_name, node in storage.get('node', {}).iteritems() %}
+  {%- for node_name, node in storage.get('node', {}).iteritems() %}
+    {%- if node.repeat is defined %}
+      {%- for i in range(node.repeat.count) %}
+        {%- set extra_params = {} %}
 
-{%- if node.name is defined and node.repeat is not defined %}
-{%- set node_name = node.name %}
+        {%- for param_name, param in node.repeat.params.iteritems() %}
+          {%- set param_count = (param.get('start', 1) + i)|string %}
+          {%- set param_value = {'value': param.value|replace(storage.repeat_count_replace_symbol, param_count.rjust(param.get('digits', 1), '0'))} %}
+          {%- if node.repeat.ip_ranges is defined %}
+            {%- for range_name, range in node.repeat.ip_ranges.iteritems() %}
+              {%- set ip_list = salt['netutils.parse_network_ranges'](range, node.repeat.count) %}
+              {%- do param_value.update({'value': param_value['value']|replace('<<' + range_name + '>>', ip_list[i])}) %}
+            {%- endfor %}
+          {%- endif %}
+          {%- do extra_params.update({param_name: {'value': param_value['value'], 'interpolate': param.get('interpolate', False)}}) %}
+        {%- endfor %}
 
-{%- if node_name in storage_by_name and storage_by_name[node_name].classes is defined %}
-{%- do node.update({'classes': storage_by_name[node_name].classes + node.get('classes', []) }) %}
-{%- endif %}
+        {%- set node_count = (node.repeat.get('start', 1) + i)|string %}
+        {%- set gen_node_name = node.name|replace(storage.repeat_count_replace_symbol, node_count.rjust(node.repeat.get('digits', 1), '0')) %}
+        {%- set gen_node = {} %}
+        {%- do gen_node.update(node) %}
+        {%- do gen_node.update({'__extra_params': extra_params}) %}
+        {%- do salt['defaults.merge'](storage_by_name, {gen_node_name: gen_node}) %}
+      {%- endfor %}
 
-{%- endif %}
+    {%- elif node.name is defined and node.repeat is not defined %}
+      {%- set node_name = node.name %}
+      {%- if node_name in storage_by_name and storage_by_name[node_name].classes is defined %}
+        {%- do node.update({'classes': storage_by_name[node_name].classes + node.get('classes', []) }) %}
+      {%- endif %}
+    {%- endif %}
+    {%- do salt['defaults.merge'](storage_by_name, {node_name: node}) %}
+  {%- endfor %}
 
-{%- do salt['defaults.merge'](storage_by_name, {node_name: node}) %}
-
-{%- endfor %}
-
-{%- for node_name, node in storage_by_name.iteritems() %}
-
-{%- if node.repeat is defined %}
-
-{%- for i in range(node.repeat.count) %}
-
-{%- set extra_params = {} %}
-
-{%- for param_name, param in node.repeat.params.iteritems() %}
-{%- set param_count = (param.get('start', 1) + i)|string %}
-{%- set param_value = {'value': param.value|replace(storage.repeat_count_replace_symbol, param_count.rjust(param.get('digits', 1), '0'))} %}
-{%- if node.repeat.ip_ranges is defined %}
-{%- for range_name, range in node.repeat.ip_ranges.iteritems() %}
-{%- set ip_list = salt['netutils.parse_network_ranges'](range, node.repeat.count) %}
-{%- do param_value.update({'value': param_value['value']|replace('<<' + range_name + '>>', ip_list[i])}) %}
-{%- endfor %}
-{%- endif %}
-{%- do extra_params.update({param_name: {'value': param_value['value'], 'interpolate': param.get('interpolate', False)}}) %}
-{%- endfor %}
-
-{%- set node_count = (node.repeat.get('start', 1) + i)|string %}
-{%- set node_name = node.name|replace(storage.repeat_count_replace_symbol, node_count.rjust(node.repeat.get('digits', 1), '0')) %}
+  {%- for node_name, node in storage_by_name.iteritems() %}
 
 {{ storage.base_dir }}/nodes/_generated/{{ node_name }}.{{ node.domain }}.yml:
   file.managed:
@@ -63,34 +62,12 @@
   - defaults:
       node: {{ node|yaml }}
       node_name: "{{ node_name }}"
-      extra_params: {{ extra_params }}
-{%- if storage.reclass_nodes_cleanup %}
+      extra_params: {{ node.get('__extra_params', {}) }}
+    {%- if storage.reclass_nodes_cleanup %}
   - require_in:
     - file: {{ storage.base_dir }}/nodes/_generated_cleanup
-{%- endif %}
+    {%- endif %}
 
-{%- endfor %}
-
-{%- else %}
-
-{{ storage.base_dir }}/nodes/_generated/{{ node.name }}.{{ node.domain }}.yml:
-  file.managed:
-  - source: salt://reclass/files/node.yml
-  - user: root
-  - group: root
-  - template: jinja
-  - makedirs: True
-  - defaults:
-      node: {{ node|yaml }}
-      node_name: "{{ node.get('name', node_name) }}"
-      extra_params: {}
-{%- if storage.reclass_nodes_cleanup %}
-  - require_in:
-    - file: {{ storage.base_dir }}/nodes/_generated_cleanup
-{%- endif %}
-
-{%- endif %}
-
-{%- endfor %}
+  {%- endfor %}
 
 {%- endif %}