Browse Source

Merge "Add introspection rules actions to add/remove traits on nodes"

tags/8.1.0
Zuul 9 months ago
parent
commit
10109622c1

+ 6
- 0
doc/source/user/usage.rst View File

@@ -123,6 +123,12 @@ Default available actions include:
123 123
   value as a list and appends value to it. If optional ``unique`` parameter is
124 124
   set to ``True``, nothing will be added if given value is already in a list.
125 125
 
126
+* ``add-trait`` adds a trait to an Ironic node. Requires a ``name`` field
127
+  with the name of the trait to add.
128
+
129
+* ``remove-trait`` removes a trait from an Ironic node. Requires a ``name``
130
+  field with the name of the trait to remove.
131
+
126 132
 Starting from Mitaka release, ``value`` field in actions supports fetching data
127 133
 from introspection, using `python string formatting notation
128 134
 <https://docs.python.org/2/library/string.html#formatspec>`_::

+ 22
- 0
ironic_inspector/node_cache.py View File

@@ -470,6 +470,28 @@ class NodeInfo(object):
470 470
             ironic=ironic,
471 471
             capabilities=ir_utils.dict_to_capabilities(existing))
472 472
 
473
+    def add_trait(self, trait, ironic=None):
474
+        """Add a trait to the node.
475
+
476
+        :param trait: trait to add
477
+        :param ironic: Ironic client to use instead of self.ironic
478
+        """
479
+        ironic = ironic or self.ironic
480
+        ironic.node.add_trait(self.uuid, trait)
481
+
482
+    def remove_trait(self, trait, ironic=None):
483
+        """Remove a trait from the node.
484
+
485
+        :param trait: trait to add
486
+        :param ironic: Ironic client to use instead of self.ironic
487
+        """
488
+        ironic = ironic or self.ironic
489
+        try:
490
+            ironic.node.remove_trait(self.uuid, trait)
491
+        except exceptions.NotFound:
492
+            LOG.debug('Trait %s is not set, cannot remove', trait,
493
+                      node_info=self)
494
+
473 495
     def delete_port(self, port, ironic=None):
474 496
         """Delete port.
475 497
 

+ 14
- 0
ironic_inspector/plugins/rules.py View File

@@ -151,3 +151,17 @@ class ExtendAttributeAction(base.RuleActionPlugin):
151 151
             return values
152 152
 
153 153
         node_info.replace_field(params['path'], _replace, default=[])
154
+
155
+
156
+class AddTraitAction(base.RuleActionPlugin):
157
+    REQUIRED_PARAMS = {'name'}
158
+
159
+    def apply(self, node_info, params, **kwargs):
160
+        node_info.add_trait(params['name'])
161
+
162
+
163
+class RemoveTraitAction(base.RuleActionPlugin):
164
+    REQUIRED_PARAMS = {'name'}
165
+
166
+    def apply(self, node_info, params, **kwargs):
167
+        node_info.remove_trait(params['name'])

+ 38
- 0
ironic_inspector/test/unit/test_plugins_rules.py View File

@@ -14,6 +14,7 @@
14 14
 
15 15
 """Tests for introspection rules plugins."""
16 16
 
17
+from ironicclient import exceptions
17 18
 import mock
18 19
 
19 20
 from ironic_inspector.common import ironic as ir_utils
@@ -222,3 +223,40 @@ class TestExtendAttributeAction(test_base.NodeTest):
222 223
         self.node.extra['value'] = [42]
223 224
         self.act.apply(self.node_info, params)
224 225
         self.assertFalse(mock_patch.called)
226
+
227
+
228
+@mock.patch('ironic_inspector.common.ironic.get_client', autospec=True)
229
+class TestAddTraitAction(test_base.NodeTest):
230
+    act = rules_plugins.AddTraitAction()
231
+    params = {'name': 'CUSTOM_FOO'}
232
+
233
+    def test_validate(self, mock_cli):
234
+        self.act.validate(self.params)
235
+        self.assertRaises(ValueError, self.act.validate, {'value': 42})
236
+
237
+    def test_add(self, mock_cli):
238
+        self.act.apply(self.node_info, self.params)
239
+        mock_cli.return_value.node.add_trait.assert_called_once_with(
240
+            self.uuid, 'CUSTOM_FOO')
241
+
242
+
243
+@mock.patch('ironic_inspector.common.ironic.get_client', autospec=True)
244
+class TestRemoveTraitAction(test_base.NodeTest):
245
+    act = rules_plugins.RemoveTraitAction()
246
+    params = {'name': 'CUSTOM_FOO'}
247
+
248
+    def test_validate(self, mock_cli):
249
+        self.act.validate(self.params)
250
+        self.assertRaises(ValueError, self.act.validate, {'value': 42})
251
+
252
+    def test_remove(self, mock_cli):
253
+        self.act.apply(self.node_info, self.params)
254
+        mock_cli.return_value.node.remove_trait.assert_called_once_with(
255
+            self.uuid, 'CUSTOM_FOO')
256
+
257
+    def test_remove_not_found(self, mock_cli):
258
+        mock_cli.return_value.node.remove_trait.side_effect = (
259
+            exceptions.NotFound('trait not found'))
260
+        self.act.apply(self.node_info, self.params)
261
+        mock_cli.return_value.node.remove_trait.assert_called_once_with(
262
+            self.uuid, 'CUSTOM_FOO')

+ 5
- 0
releasenotes/notes/trait-actions-eec05cbb6a944619.yaml View File

@@ -0,0 +1,5 @@
1
+---
2
+features:
3
+  - |
4
+    Adds new introspection rules actions to add or remove traits on nodes:
5
+    ``add-trait`` and ``remove-trait``.

+ 2
- 0
setup.cfg View File

@@ -60,6 +60,8 @@ ironic_inspector.rules.actions =
60 60
     set-attribute = ironic_inspector.plugins.rules:SetAttributeAction
61 61
     set-capability = ironic_inspector.plugins.rules:SetCapabilityAction
62 62
     extend-attribute = ironic_inspector.plugins.rules:ExtendAttributeAction
63
+    add-trait = ironic_inspector.plugins.rules:AddTraitAction
64
+    remove-trait = ironic_inspector.plugins.rules:RemoveTraitAction
63 65
 ironic_inspector.pxe_filter =
64 66
     dnsmasq = ironic_inspector.pxe_filter.dnsmasq:DnsmasqFilter
65 67
     iptables = ironic_inspector.pxe_filter.iptables:IptablesFilter

Loading…
Cancel
Save