@@ -79,3 +79,142 @@ def test_action_show(self):
7979 self .assertIn (action_uuid , action )
8080 self .assert_table_structure ([action ],
8181 self .detailed_list_fields )
82+
83+
84+ class ActionUpdateTests (base .TestCase ):
85+ """Functional tests for action update functionality."""
86+
87+ # Use API version 1.5 for action update tests
88+ api_version = 1.5
89+ dummy_name = 'dummy'
90+ audit_template_name = 'b' + uuidutils .generate_uuid ()
91+ audit_uuid = None
92+ action_uuid = None
93+
94+ @classmethod
95+ def setUpClass (cls ):
96+ # Create audit template
97+ template_raw_output = cls .watcher (
98+ 'audittemplate create %s dummy -s dummy' % cls .audit_template_name )
99+ template_output = cls .parse_show_as_object (template_raw_output )
100+
101+ # Create audit
102+ audit_output = cls .parse_show_as_object (cls .watcher (
103+ 'audit create -a %s' % template_output ['Name' ]))
104+ cls .audit_uuid = audit_output ['UUID' ]
105+
106+ # Wait for audit to complete
107+ audit_created = test_utils .call_until_true (
108+ func = functools .partial (cls .has_audit_created , cls .audit_uuid ),
109+ duration = 600 ,
110+ sleep_for = 2 )
111+ if not audit_created :
112+ raise Exception ('Audit has not been succeeded' )
113+
114+ # Get an action to test updates on
115+ action_list = cls .parse_show (cls .watcher ('action list --audit %s'
116+ % cls .audit_uuid ))
117+ if action_list :
118+ cls .action_uuid = list (action_list [0 ])[0 ]
119+
120+ @classmethod
121+ def tearDownClass (cls ):
122+ # Clean up: Delete Action Plan and all related actions
123+ if cls .audit_uuid :
124+ output = cls .parse_show (
125+ cls .watcher ('actionplan list --audit %s' % cls .audit_uuid ))
126+ if output :
127+ action_plan_uuid = list (output [0 ])[0 ]
128+ raw_output = cls .watcher (
129+ 'actionplan delete %s' % action_plan_uuid )
130+ cls .assertOutput ('' , raw_output )
131+
132+ # Delete audit
133+ raw_output = cls .watcher ('audit delete %s' % cls .audit_uuid )
134+ cls .assertOutput ('' , raw_output )
135+
136+ # Delete template
137+ raw_output = cls .watcher (
138+ 'audittemplate delete %s' % cls .audit_template_name )
139+ cls .assertOutput ('' , raw_output )
140+
141+ def test_action_update_with_state_and_reason (self ):
142+ """Test updating action state with reason using API 1.5"""
143+ if not self .action_uuid :
144+ self .skipTest ("No actions available for testing" )
145+
146+ # Update action state to SKIPPED with reason
147+ raw_output = self .watcher (
148+ 'action update --state SKIPPED --reason "Functional test skip" %s'
149+ % self .action_uuid )
150+
151+ # Verify the action was updated
152+ action = self .parse_show_as_object (
153+ self .watcher ('action show %s' % self .action_uuid ))
154+ self .assertEqual ('SKIPPED' , action ['State' ])
155+ self .assertEqual ('Action skipped by user. Reason: Functional test '
156+ 'skip' , action ['Status Message' ])
157+
158+ # Verify output contains the action UUID
159+ self .assertIn (self .action_uuid , raw_output )
160+
161+ def test_action_update_with_state_only (self ):
162+ """Test updating action state without reason"""
163+ if not self .action_uuid :
164+ self .skipTest ("No actions available for testing" )
165+
166+ # Update action state to SKIPPED without reason
167+ raw_output = self .watcher (
168+ 'action update --state SKIPPED %s' % self .action_uuid )
169+
170+ # Verify the action was updated
171+ action = self .parse_show_as_object (
172+ self .watcher ('action show %s' % self .action_uuid ))
173+ self .assertEqual ('SKIPPED' , action ['State' ])
174+
175+ # Verify output contains the action UUID
176+ self .assertIn (self .action_uuid , raw_output )
177+
178+ def test_action_update_missing_state_fails (self ):
179+ """Test that action update fails when no state is provided"""
180+ if not self .action_uuid :
181+ self .skipTest ("No actions available for testing" )
182+
183+ # This should fail because --state is required
184+ raw_output = self .watcher (
185+ 'action update %s' % self .action_uuid , fail_ok = True )
186+
187+ # Should contain error message about missing state
188+ self .assertIn (
189+ 'At least one field update is required for this operation' ,
190+ raw_output )
191+
192+ def test_action_update_nonexistent_action_fails (self ):
193+ """Test that action update fails for non-existent action"""
194+ fake_uuid = uuidutils .generate_uuid ()
195+
196+ # This should fail because the action doesn't exist
197+ raw_output = self .watcher (
198+ 'action update --state SKIPPED %s' % fake_uuid , fail_ok = True )
199+
200+ # Should contain error message about action not found
201+ self .assertIn ('404' , raw_output )
202+
203+
204+ class ActionUpdateApiVersionTests (base .TestCase ):
205+ """Test action update functionality with different API versions."""
206+
207+ # Use API version 1.0 to test version checking
208+ api_version = 1.0
209+
210+ def test_action_update_unsupported_api_version (self ):
211+ """Test that action update fails with API version < 1.5"""
212+ fake_uuid = uuidutils .generate_uuid ()
213+
214+ # This should fail because API version 1.0 doesn't support updates
215+ raw_output = self .watcher (
216+ 'action update --state SKIPPED %s' % fake_uuid , fail_ok = True )
217+
218+ # Should contain error message about unsupported API version
219+ self .assertIn ('not supported in API version' , raw_output )
220+ self .assertIn ('Minimum required version is 1.5' , raw_output )
0 commit comments