1515package argocompiler
1616
1717import (
18+ "encoding/json"
19+ "fmt"
20+
21+ wfapi "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
22+ log "github.com/sirupsen/logrus"
1823 "google.golang.org/protobuf/types/known/structpb"
24+ "k8s.io/apimachinery/pkg/util/strategicpatch"
1925)
2026
2127func (c * workflowCompiler ) AddKubernetesSpec (name string , kubernetesSpec * structpb.Struct ) error {
@@ -25,3 +31,52 @@ func (c *workflowCompiler) AddKubernetesSpec(name string, kubernetesSpec *struct
2531 }
2632 return nil
2733}
34+
35+ // ApplyWorkflowSpecPatch applies a JSON patch to the compiled workflow specification.
36+ // It validates the JSON and applies it using Kubernetes strategic merge patch.
37+ // Only the workflow's "spec" field can be patched for security reasons.
38+ func (c * workflowCompiler ) ApplyWorkflowSpecPatch (patchJSON string ) error {
39+ if c .wf == nil {
40+ return fmt .Errorf ("workflow is nil" )
41+ }
42+
43+ // Check for empty patch string
44+ if patchJSON == "" {
45+ log .Debug ("Empty workflow spec patch string provided, skipping patching" )
46+ return nil
47+ }
48+
49+ log .Debug ("Applying workflow spec patch" )
50+
51+ // Validate that the patch is valid JSON by attempting to unmarshal it
52+ var specPatchValidation map [string ]interface {}
53+ if err := json .Unmarshal ([]byte (patchJSON ), & specPatchValidation ); err != nil {
54+ return fmt .Errorf ("invalid JSON in COMPILED_PIPELINE_SPEC_PATCH: %w" , err )
55+ }
56+
57+ // Check if the patch is empty (no fields to patch)
58+ if len (specPatchValidation ) == 0 {
59+ log .Debug ("Empty workflow spec patch provided, skipping patching" )
60+ return nil
61+ }
62+
63+ // Convert the current workflow spec to JSON
64+ originalSpecJSON , err := json .Marshal (c .wf .Spec )
65+ if err != nil {
66+ return fmt .Errorf ("failed to marshal workflow spec to JSON: %w" , err )
67+ }
68+
69+ // Apply the strategic merge patch to the spec directly
70+ patchedSpecJSON , err := strategicpatch .StrategicMergePatch (originalSpecJSON , []byte (patchJSON ), wfapi.WorkflowSpec {})
71+ if err != nil {
72+ return fmt .Errorf ("failed to apply strategic merge patch to workflow spec: %w" , err )
73+ }
74+
75+ // Unmarshal the patched spec back into the workflow
76+ if err := json .Unmarshal (patchedSpecJSON , & c .wf .Spec ); err != nil {
77+ return fmt .Errorf ("failed to unmarshal patched workflow spec: %w" , err )
78+ }
79+
80+ log .Debug ("Successfully applied workflow spec patch" )
81+ return nil
82+ }
0 commit comments