blob: 4f9e09e64e97237d76a04bdac3757788b274592f [file] [log] [blame]
Ales Komarek166cc672016-07-27 14:17:22 +02001# -*- coding: utf-8 -*-
2'''
3Management of reclass metadata
4==============================
5
6.. code-block:: yaml
7
8 node01:
9 reclass.node_present:
10 - name: hostaname.domain.com
11 - path: _generated
12 - cluster: default
13 - environment: prd
14 - classes:
15 - neco.service.neco
16 - neco2.class.neco.dal
17 - parameters:
18 neco: value1
19 neco2: value2
20
Adam Tengler8a1cf402017-05-16 10:59:35 +000021.. code-block:: yaml
22
23 node_meta_01:
24 reclass.cluster_meta_present:
25 - name: my_key
26 - value: my_value
Ales Komarek166cc672016-07-27 14:17:22 +020027'''
Adam Tengler8a1cf402017-05-16 10:59:35 +000028from __future__ import absolute_import
29
Adam Tengler805666d2017-05-15 16:01:13 +000030import json
Adam Tengler8a1cf402017-05-16 10:59:35 +000031import os
Adam Tengler805666d2017-05-15 16:01:13 +000032import six
Ales Komarek166cc672016-07-27 14:17:22 +020033
Adam Tengler8a1cf402017-05-16 10:59:35 +000034from reclass.config import find_and_read_configfile
35
Ales Komarek166cc672016-07-27 14:17:22 +020036
37def __virtual__():
38 '''
Adam Tengler805666d2017-05-15 16:01:13 +000039 Only load if the reclass module is in __salt__
Ales Komarek166cc672016-07-27 14:17:22 +020040 '''
Adam Tengler805666d2017-05-15 16:01:13 +000041 return 'reclass' if 'reclass.node_list' in __salt__ else False
42
43
Adam Tengler8a1cf402017-05-16 10:59:35 +000044def _get_classes_dir():
45 defaults = find_and_read_configfile()
46 return os.path.join(defaults.get('inventory_base_uri'), 'classes')
47
48
49def _get_cluster_dir():
50 classes_dir = _get_classes_dir()
51 return os.path.join(classes_dir, 'cluster')
52
53
Adam Tengler805666d2017-05-15 16:01:13 +000054def node_present(name, path=None, cluster="default", environment="prd", classes=None, parameters=None, **kwargs):
55 '''
56 Ensure that the reclass node exists
57
58 :param name: new node FQDN
59 :param path: custom path in nodes for new node
60 :param classes: classes given to the new node
61 :param parameters: parameters given to the new node
62 :param environment: node's environment
63 :param cluster: node's cluster
64
65 '''
66 ret = {'name': name,
67 'changes': {},
68 'result': True,
69 'comment': 'Node "{0}" already exists and it is in correct state'.format(name)}
70
71 # Check if node is already present
72 node = __salt__['reclass.node_get'](name, **kwargs)
73
74 if 'Error' in node:
75 # Create node
76 __salt__['reclass.node_create'](name, path, cluster, environment, classes, parameters, **kwargs)
77 ret['comment'] = 'Node "{0}" has been created'.format(name)
78 ret['changes']['Node'] = 'Created'
79 return ret
Ales Komarek166cc672016-07-27 14:17:22 +020080
Adam Tengler8a1cf402017-05-16 10:59:35 +000081
Adam Tengler23d965f2017-05-16 19:14:51 +000082def dynamic_node_present(name, node_data={}, class_mapping={}, **kwargs):
83 '''
84 Classify node, create cluster level overrides and node metadata
85
86 :param name: node FQDN
87 :param node_data: dictionary of known informations about the node
88 :param class_mapping: dictionary of classes and parameters, with conditions
89
90 '''
91 ret = {'name': name,
92 'changes': {},
93 'result': True,
94 'comment': 'Node "{0}" already exists and it is in correct state'.format(name)}
95
96 classify_ret = __salt__['reclass.node_classify'](name, node_data, class_mapping, **kwargs)
97 ret['comment'] = 'Node "{0}" has been created'.format(name)
98 ret['changes']['Node'] = classify_ret
99
100 return ret
101
102
Adam Tengler8a1cf402017-05-16 10:59:35 +0000103def cluster_meta_present(name, value, file_name="overrides.yml", cluster="", **kwargs):
104 '''
105 Ensures that the cluster metadata entry exists
106
107 :param name: Metadata entry name
108 :param value: Metadata entry value
109 :param file_name: Name of metadata file, defaults to overrides.yml
110 :param cluster: Name of cluster directory to put the metadata file into, optional
111 '''
112 value = value or ""
113 cluster = cluster or ""
114 path = os.path.join(_get_cluster_dir(), cluster, file_name)
115 ret = {'name': name,
116 'changes': {},
117 'result': True,
118 'comment': 'Cluster metadata entry "{0}" already exists and is in correct state'.format(name)}
119 meta_check = __salt__['reclass.cluster_meta_get'](name, path, **kwargs)
120 if not meta_check:
121 __salt__['reclass.cluster_meta_set'](name, value, path, **kwargs)
122 ret['comment'] = 'Cluster meta entry {0} has been created'.format(name)
123 ret['changes']['Meta Entry'] = 'Cluster meta entry %s: "%s" has been created' % (name, value)
124 elif 'Error' in meta_check:
125 ret['comment'] = meta_check.get('Error')
126 ret['result'] = False
127 elif meta_check[name] != value:
128 __salt__['reclass.cluster_meta_set'](name, value, path, **kwargs)
129 ret['comment'] = 'Cluster metadata entry %s has been changed' % (name,)
130 ret['changes']['Old Meta Entry'] = '%s: "%s"' % (name, meta_check[name])
131 ret['changes']['New Meta Entry'] = '%s: "%s"' % (name, value)
132 return ret
133
134
135def cluster_meta_absent(name, file_name="overrides.yml", cluster="", **kwargs):
136 '''
137 Ensures that the cluster metadata entry does not exist
138
139 :param name: Metadata entry name
140 :param file_name: Name of metadata file, defaults to overrides.yml
141 :param cluster: Name of cluster directory to put the metadata file into, optional
142 '''
143 cluster = cluster or ""
144 path = os.path.join(_get_cluster_dir(), cluster, file_name)
145 ret = {'name': name,
146 'changes': {},
147 'result': True,
148 'comment': 'Cluster metadata entry "{0}" is already absent'.format(name)}
149 meta_check = __salt__['reclass.cluster_meta_get'](name, path, **kwargs)
150 if meta_check:
151 __salt__['reclass.cluster_meta_delete'](name, path, **kwargs)
152 ret['comment'] = 'Cluster metadata entry {0} has been deleted'.format(name)
153 ret['changes']['Meta Entry'] = 'Cluster metadata entry %s: "%s" has been deleted' % (name, meta_check[name])
154 elif 'Error' in meta_check:
155 ret['comment'] = meta_check.get('Error')
156 ret['result'] = False
157 return ret
158