From 948c5c826732ea7234ab99d8a87491094afeb7ff Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Wed, 26 Jul 2023 21:05:42 +0000 Subject: [PATCH] fix(server): handle PATCH in http/s server (#2677) (#14530) Signed-off-by: mmerrill3 --- server/server.go | 6 +++--- test/e2e/app_management_test.go | 18 ++++++++++++++++++ test/e2e/fixture/app/actions.go | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/server/server.go b/server/server.go index fdce390701c4c..47d00d9455e9f 100644 --- a/server/server.go +++ b/server/server.go @@ -508,11 +508,11 @@ func (a *ArgoCDServer) Run(ctx context.Context, listeners *Listeners) { var httpL net.Listener var httpsL net.Listener if !a.useTLS() { - httpL = tcpm.Match(cmux.HTTP1Fast()) + httpL = tcpm.Match(cmux.HTTP1Fast("PATCH")) grpcL = tcpm.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc")) } else { // We first match on HTTP 1.1 methods. - httpL = tcpm.Match(cmux.HTTP1Fast()) + httpL = tcpm.Match(cmux.HTTP1Fast("PATCH")) // If not matched, we assume that its TLS. tlsl := tcpm.Match(cmux.Any()) @@ -527,7 +527,7 @@ func (a *ArgoCDServer) Run(ctx context.Context, listeners *Listeners) { // Now, we build another mux recursively to match HTTPS and gRPC. tlsm = cmux.New(tlsl) - httpsL = tlsm.Match(cmux.HTTP1Fast()) + httpsL = tlsm.Match(cmux.HTTP1Fast("PATCH")) grpcL = tlsm.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc")) } diff --git a/test/e2e/app_management_test.go b/test/e2e/app_management_test.go index 8bff935e99bdb..8c77661067a7a 100644 --- a/test/e2e/app_management_test.go +++ b/test/e2e/app_management_test.go @@ -417,6 +417,24 @@ func TestDeleteAppResource(t *testing.T) { Expect(HealthIs(health.HealthStatusMissing)) } +// Fix for issue #2677, support PATCH in HTTP service +func TestPatchHttp(t *testing.T) { + ctx := Given(t) + + ctx. + Path(guestbookPath). + When(). + CreateApp(). + Sync(). + PatchAppHttp(`{"metadata": {"labels": { "test": "patch" }, "annotations": { "test": "patch" }}}`). + Then(). + And(func(app *Application) { + assert.Equal(t, "patch", app.Labels["test"]) + assert.Equal(t, "patch", app.Annotations["test"]) + }) + +} + // demonstrate that we cannot use a standard sync when an immutable field is changed, we must use "force" func TestImmutableChange(t *testing.T) { SkipOnEnv(t, "OPENSHIFT") diff --git a/test/e2e/fixture/app/actions.go b/test/e2e/fixture/app/actions.go index bfe95f628daa1..314731d754e8d 100644 --- a/test/e2e/fixture/app/actions.go +++ b/test/e2e/fixture/app/actions.go @@ -1,12 +1,14 @@ package app import ( + "encoding/json" "fmt" "os" log "github.com/sirupsen/logrus" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + client "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" . "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/argoproj/argo-cd/v2/test/e2e/fixture" "github.com/argoproj/argo-cd/v2/util/errors" @@ -250,6 +252,28 @@ func (a *Actions) PatchApp(patch string) *Actions { return a } +func (a *Actions) PatchAppHttp(patch string) *Actions { + a.context.t.Helper() + var application Application + var patchType = "merge" + var appName = a.context.AppQualifiedName() + var appNamespace = a.context.AppNamespace() + patchRequest := &client.ApplicationPatchRequest{ + Name: &appName, + PatchType: &patchType, + Patch: &patch, + AppNamespace: &appNamespace, + } + jsonBytes, err := json.MarshalIndent(patchRequest, "", " ") + errors.CheckError(err) + err = fixture.DoHttpJsonRequest("PATCH", + fmt.Sprintf("/api/v1/applications/%v", appName), + &application, + jsonBytes...) + errors.CheckError(err) + return a +} + func (a *Actions) AppSet(flags ...string) *Actions { a.context.t.Helper() args := []string{"app", "set", a.context.AppQualifiedName()}