From aaaf2fac75495dddab60810ee0725aff7fd3589b Mon Sep 17 00:00:00 2001 From: isubasinghe Date: Tue, 24 Dec 2024 17:13:43 +1100 Subject: [PATCH 1/2] fix: search and replace null bytes for postgres only Signed-off-by: isubasinghe --- persist/sqldb/workflow_archive.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/persist/sqldb/workflow_archive.go b/persist/sqldb/workflow_archive.go index f6d40f4a6e1e..9882487f9392 100644 --- a/persist/sqldb/workflow_archive.go +++ b/persist/sqldb/workflow_archive.go @@ -1,8 +1,10 @@ package sqldb import ( + "bytes" "encoding/json" "fmt" + "strings" "time" log "github.com/sirupsen/logrus" @@ -20,8 +22,9 @@ import ( ) const ( - archiveTableName = "argo_archived_workflows" - archiveLabelsTableName = archiveTableName + "_labels" + archiveTableName = "argo_archived_workflows" + archiveLabelsTableName = archiveTableName + "_labels" + postgresNullReplacement = "ARGO_POSTGRES_NULL_REPLACEMENT" ) type archivedWorkflowMetadata struct { @@ -103,6 +106,9 @@ func (r *workflowArchive) ArchiveWorkflow(wf *wfv1.Workflow) error { if err != nil { return err } + if r.dbType == Postgres { + workflow = bytes.ReplaceAll(workflow, []byte("\\u0000"), []byte(postgresNullReplacement)) + } return r.session.Tx(func(sess db.Session) error { _, err := sess.SQL(). DeleteFrom(archiveTableName). @@ -387,6 +393,9 @@ func (r *workflowArchive) GetWorkflow(uid string, namespace string, name string) return nil, err } var wf *wfv1.Workflow + if r.dbType == Postgres { + archivedWf.Workflow = strings.ReplaceAll(archivedWf.Workflow, postgresNullReplacement, "\\u0000") + } err = json.Unmarshal([]byte(archivedWf.Workflow), &wf) if err != nil { return nil, err From 2b685b3ff6b34931faa0d0f3c8afa412dfc47706 Mon Sep 17 00:00:00 2001 From: isubasinghe Date: Fri, 3 Jan 2025 19:59:30 +1100 Subject: [PATCH 2/2] ci: added a test to capture postgres null bytes being restored correctly Signed-off-by: isubasinghe --- test/e2e/argo_server_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/e2e/argo_server_test.go b/test/e2e/argo_server_test.go index d49c3d5f3713..d451a46628b5 100644 --- a/test/e2e/argo_server_test.go +++ b/test/e2e/argo_server_test.go @@ -2135,6 +2135,42 @@ func (s *ArgoServerSuite) TestRateLimitHeader() { }) } +func (s *ArgoServerSuite) TestPostgresNullBytes() { + // only meaningful for postgres, but shouldn't fail for mysql. + var uid types.UID + _ = uid + + s.Given(). + Workflow(` +metadata: + generateName: archie- + labels: + foo: 1 +spec: + entrypoint: run-archie + templates: + - name: run-archie + container: + image: argoproj/argosay:v2 + args: [echo, "hello \u0000"]`). + When(). + SubmitWorkflow(). + WaitForWorkflow(fixtures.ToBeArchived). + Then(). + ExpectWorkflow(func(t *testing.T, metadata *metav1.ObjectMeta, status *wfv1.WorkflowStatus) { + uid = metadata.UID + }) + + j := s.e().GET("/api/v1/archived-workflows/{uid}", uid). + Expect(). + Status(200). + JSON() + j. + Path("$.spec.templates[0].container.args[1]"). + IsEqual("hello \u0000") + +} + func TestArgoServerSuite(t *testing.T) { suite.Run(t, new(ArgoServerSuite)) }