Skip to content

Commit c9297c0

Browse files
bergmannfclaude
andcommitted
Integrate executor into investigation flow to execute actions
Extends the main investigate command to automatically execute actions returned by investigations using the executor framework. This completes the migration from direct external system calls to the action pattern. Changes: - Add executeActions() helper that creates an executor and runs all actions from an InvestigationResult - Execute CCAM actions after CCAM investigation runs - Execute main investigation actions after the alert investigation runs - Configure executor with sensible defaults: 3 retries, concurrent execution for independent actions, continue on error - Log action execution success/failure for observability This enables investigations like CHGM to return actions instead of directly calling OCM/PagerDuty APIs, improving testability and separation of concerns. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 0a00113 commit c9297c0

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

cadctl/cmd/investigate/investigate.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ limitations under the License.
1717
package investigate
1818

1919
import (
20+
"context"
2021
"errors"
2122
"fmt"
2223
"os"
2324
"strconv"
2425
"strings"
2526

27+
"github.com/openshift/configuration-anomaly-detection/pkg/executor"
2628
investigations "github.com/openshift/configuration-anomaly-detection/pkg/investigations"
2729
"github.com/openshift/configuration-anomaly-detection/pkg/investigations/ccam"
2830
investigation "github.com/openshift/configuration-anomaly-detection/pkg/investigations/investigation"
@@ -196,12 +198,23 @@ func run(cmd *cobra.Command, _ []string) error {
196198
}
197199
updateMetrics(alertInvestigation.Name(), &result)
198200

201+
// Execute ccam actions if any
202+
if err := executeActions(builder, &result, ocmClient, pdClient, "ccam"); err != nil {
203+
return fmt.Errorf("failed to execute ccam actions: %w", err)
204+
}
205+
199206
logging.Infof("Starting investigation for %s", alertInvestigation.Name())
200207
result, err = alertInvestigation.Run(builder)
201208
if err != nil {
202209
return err
203210
}
204211
updateMetrics(alertInvestigation.Name(), &result)
212+
213+
// Execute investigation actions if any
214+
if err := executeActions(builder, &result, ocmClient, pdClient, alertInvestigation.Name()); err != nil {
215+
return fmt.Errorf("failed to execute %s actions: %w", alertInvestigation.Name(), err)
216+
}
217+
205218
return updateIncidentTitle(pdClient)
206219
}
207220

@@ -283,3 +296,52 @@ func updateIncidentTitle(pdClient *pagerduty.SdkClient) error {
283296
}
284297
return nil
285298
}
299+
300+
// executeActions executes any actions returned by an investigation
301+
func executeActions(
302+
builder investigation.ResourceBuilder,
303+
result *investigation.InvestigationResult,
304+
ocmClient *ocm.SdkClient,
305+
pdClient *pagerduty.SdkClient,
306+
investigationName string,
307+
) error {
308+
// If no actions, return early
309+
if len(result.Actions) == 0 {
310+
logging.Debug("No actions to execute")
311+
return nil
312+
}
313+
314+
// Build resources to get cluster and notes
315+
resources, err := builder.Build()
316+
if err != nil {
317+
return fmt.Errorf("failed to build resources for action execution: %w", err)
318+
}
319+
320+
// Create executor
321+
exec := executor.NewExecutor(ocmClient, pdClient, logging.RawLogger)
322+
323+
// Execute actions with default options
324+
input := &executor.ExecutorInput{
325+
InvestigationName: investigationName,
326+
Actions: result.Actions,
327+
Cluster: resources.Cluster,
328+
Notes: resources.Notes,
329+
Options: executor.ExecutionOptions{
330+
DryRun: false,
331+
StopOnError: false, // Continue executing actions even if one fails
332+
MaxRetries: 3,
333+
ConcurrentActions: true, // Use concurrent execution for better performance
334+
},
335+
}
336+
337+
logging.Infof("Executing %d actions for %s", len(result.Actions), investigationName)
338+
if err := exec.Execute(context.Background(), input); err != nil {
339+
// Log the error but don't fail the investigation
340+
// This matches the current behavior where we log failures but continue
341+
logging.Errorf("Action execution failed for %s: %v", investigationName, err)
342+
return err
343+
}
344+
345+
logging.Infof("Successfully executed all actions for %s", investigationName)
346+
return nil
347+
}

0 commit comments

Comments
 (0)