From 7afbb0bf6e2e7306ccac583cb4789403a0701339 Mon Sep 17 00:00:00 2001 From: Aidan Oldershaw Date: Mon, 30 Mar 2020 12:10:39 -0400 Subject: [PATCH] atc: behaviour: add flag to enable archive pipeline concourse/concourse#5315 - as per https://github.com/concourse/concourse/pull/5346#issuecomment-605023872, the ability to archive pipelines is now behind an api flag `enable-archive-pipeline`. Signed-off-by: Aidan Oldershaw Co-authored-by: James Thomson --- atc/api/api_suite_test.go | 2 ++ atc/api/handler.go | 4 +++- atc/api/pipelineserver/archive.go | 4 ++++ atc/api/pipelineserver/archive_test.go | 23 +++++++++++++++++++++++ atc/api/pipelineserver/server.go | 23 +++++++++++++---------- atc/atccmd/command.go | 7 +++++-- atc/integration/archiving_test.go | 24 ++++++++++++++++++++---- docker-compose.yml | 1 + 8 files changed, 71 insertions(+), 17 deletions(-) diff --git a/atc/api/api_suite_test.go b/atc/api/api_suite_test.go index 497ec9644af..28345439c94 100644 --- a/atc/api/api_suite_test.go +++ b/atc/api/api_suite_test.go @@ -198,6 +198,8 @@ var _ = BeforeEach(func() { time.Second, dbWall, fakeClock, + + true, /* enableArchivePipeline */ ) Expect(err).NotTo(HaveOccurred()) diff --git a/atc/api/handler.go b/atc/api/handler.go index 19c32bda307..0bbe7b2f462 100644 --- a/atc/api/handler.go +++ b/atc/api/handler.go @@ -74,6 +74,8 @@ func NewHandler( interceptUpdateInterval time.Duration, dbWall db.Wall, clock clock.Clock, + + enableArchivePipeline bool, ) (http.Handler, error) { absCLIDownloadsDir, err := filepath.Abs(cliDownloadsDir) @@ -91,7 +93,7 @@ func NewHandler( resourceServer := resourceserver.NewServer(logger, secretManager, varSourcePool, dbCheckFactory, dbResourceFactory, dbResourceConfigFactory) versionServer := versionserver.NewServer(logger, externalURL) - pipelineServer := pipelineserver.NewServer(logger, dbTeamFactory, dbPipelineFactory, externalURL) + pipelineServer := pipelineserver.NewServer(logger, dbTeamFactory, dbPipelineFactory, externalURL, enableArchivePipeline) configServer := configserver.NewServer(logger, dbTeamFactory, secretManager) ccServer := ccserver.NewServer(logger, dbTeamFactory, externalURL) workerServer := workerserver.NewServer(logger, dbTeamFactory, dbWorkerFactory) diff --git a/atc/api/pipelineserver/archive.go b/atc/api/pipelineserver/archive.go index 8f089fc9920..880ff03321a 100644 --- a/atc/api/pipelineserver/archive.go +++ b/atc/api/pipelineserver/archive.go @@ -8,6 +8,10 @@ import ( func (s *Server) ArchivePipeline(pipelineDB db.Pipeline) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !s.enableArchivePipeline { + http.Error(w, "endpoint is not enabled", http.StatusForbidden) + return + } s.logger.Debug("archive-pipeline") err := pipelineDB.Archive() if err != nil { diff --git a/atc/api/pipelineserver/archive_test.go b/atc/api/pipelineserver/archive_test.go index eb8b24de81c..6ccd5fe9535 100644 --- a/atc/api/pipelineserver/archive_test.go +++ b/atc/api/pipelineserver/archive_test.go @@ -2,6 +2,7 @@ package pipelineserver_test import ( "errors" + "io/ioutil" "net/http" "net/http/httptest" @@ -31,6 +32,7 @@ var _ = Describe("Archive Handler", func() { new(dbfakes.FakeTeamFactory), new(dbfakes.FakePipelineFactory), "", + true, /* enableArchivePipeline */ ) dbPipeline = new(dbfakes.FakePipeline) handler = server.ArchivePipeline(dbPipeline) @@ -65,4 +67,25 @@ var _ = Describe("Archive Handler", func() { Expect(fakeLogger.ErrorCallCount()).To(Equal(0)) }) + + Context("when the endpoint is not enabled", func() { + BeforeEach(func() { + server = pipelineserver.NewServer( + fakeLogger, + new(dbfakes.FakeTeamFactory), + new(dbfakes.FakePipelineFactory), + "", + false, /* enableArchivePipeline */ + ) + handler = server.ArchivePipeline(dbPipeline) + }) + + It("responds with status Forbidden", func() { + handler.ServeHTTP(recorder, request) + + Expect(recorder.Code).To(Equal(http.StatusForbidden)) + body, _ := ioutil.ReadAll(recorder.Body) + Expect(body).To(Equal([]byte("endpoint is not enabled\n"))) + }) + }) }) diff --git a/atc/api/pipelineserver/server.go b/atc/api/pipelineserver/server.go index 5c210ace62c..95fef4c3589 100644 --- a/atc/api/pipelineserver/server.go +++ b/atc/api/pipelineserver/server.go @@ -7,11 +7,12 @@ import ( ) type Server struct { - logger lager.Logger - teamFactory db.TeamFactory - rejector auth.Rejector - pipelineFactory db.PipelineFactory - externalURL string + logger lager.Logger + teamFactory db.TeamFactory + rejector auth.Rejector + pipelineFactory db.PipelineFactory + externalURL string + enableArchivePipeline bool } func NewServer( @@ -19,12 +20,14 @@ func NewServer( teamFactory db.TeamFactory, pipelineFactory db.PipelineFactory, externalURL string, + enableArchivePipeline bool, ) *Server { return &Server{ - logger: logger, - teamFactory: teamFactory, - rejector: auth.UnauthorizedRejector{}, - pipelineFactory: pipelineFactory, - externalURL: externalURL, + logger: logger, + teamFactory: teamFactory, + rejector: auth.UnauthorizedRejector{}, + pipelineFactory: pipelineFactory, + externalURL: externalURL, + enableArchivePipeline: enableArchivePipeline, } } diff --git a/atc/atccmd/command.go b/atc/atccmd/command.go index 59e4180d03d..fe2582e18ae 100644 --- a/atc/atccmd/command.go +++ b/atc/atccmd/command.go @@ -231,8 +231,9 @@ type RunCommand struct { ConfigRBAC string `long:"config-rbac" description:"Customize RBAC role-action mapping."` - SystemClaimKey string `long:"system-claim-key" default:"aud" description:"The token claim key to use when matching system-claim-values"` - SystemClaimValues []string `long:"system-claim-value" default:"concourse-worker" description:"Configure which token requests should be considered 'system' requests."` + SystemClaimKey string `long:"system-claim-key" default:"aud" description:"The token claim key to use when matching system-claim-values"` + SystemClaimValues []string `long:"system-claim-value" default:"concourse-worker" description:"Configure which token requests should be considered 'system' requests."` + EnableArchivePipeline bool `long:"enable-archive-pipeline" description:"Enable /api/v1/teams/{team}/pipelines/{pipeline}/archive endpoint."` } type Migration struct { @@ -1734,6 +1735,8 @@ func (cmd *RunCommand) constructAPIHandler( time.Minute, dbWall, clock.NewClock(), + + cmd.EnableArchivePipeline, ) } diff --git a/atc/integration/archiving_test.go b/atc/integration/archiving_test.go index 4b395a2ba4a..0d56fdc1ca4 100644 --- a/atc/integration/archiving_test.go +++ b/atc/integration/archiving_test.go @@ -20,8 +20,11 @@ var _ = Describe("ATC Integration Test", func() { ) BeforeEach(func() { - atcURL = fmt.Sprintf("http://localhost:%v", cmd.BindPort) + cmd.EnableArchivePipeline = true + }) + JustBeforeEach(func() { + atcURL = fmt.Sprintf("http://localhost:%v", cmd.BindPort) runner, err := cmd.Runner([]string{}) Expect(err).NotTo(HaveOccurred()) @@ -39,7 +42,6 @@ var _ = Describe("ATC Integration Test", func() { }) It("can archive pipelines", func() { - atcURL := fmt.Sprintf("http://localhost:%v", cmd.BindPort) client := login(atcURL, "test", "test") givenAPipeline(client, "pipeline") whenIArchiveIt(client, "pipeline") @@ -47,6 +49,19 @@ var _ = Describe("ATC Integration Test", func() { Expect(pipeline.Archived).To(BeTrue(), "pipeline was not archived") Expect(pipeline.Paused).To(BeTrue(), "pipeline was not paused") }) + + Context("when the archiving pipeline endpoint is not enabled", func() { + BeforeEach(func() { + cmd.EnableArchivePipeline = false + }) + + It("returns an error", func() { + client := login(atcURL, "test", "test") + givenAPipeline(client, "pipeline") + response := whenIArchiveIt(client, "pipeline") + Expect(response.StatusCode).To(Equal(http.StatusForbidden)) + }) + }) }) func givenAPipeline(client concourse.Client, pipelineName string) { @@ -59,15 +74,16 @@ jobs: Expect(err).NotTo(HaveOccurred()) } -func whenIArchiveIt(client concourse.Client, pipelineName string) { +func whenIArchiveIt(client concourse.Client, pipelineName string) *http.Response { httpClient := client.HTTPClient() request, _ := http.NewRequest( "PUT", client.URL()+"/api/v1/teams/main/pipelines/"+pipelineName+"/archive", nil, ) - _, err := httpClient.Do(request) + response, err := httpClient.Do(request) Expect(err).ToNot(HaveOccurred()) + return response } func getPipeline(client concourse.Client, pipelineName string) atc.Pipeline { diff --git a/docker-compose.yml b/docker-compose.yml index 5618630a7af..0234066b2b1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,6 +32,7 @@ services: CONCOURSE_CLUSTER_NAME: dev CONCOURSE_CLIENT_SECRET: Y29uY291cnNlLXdlYgo= CONCOURSE_TSA_CLIENT_SECRET: Y29uY291cnNlLXdvcmtlcgo= + CONCOURSE_ENABLE_ARCHIVE_PIPELINE: "true" worker: build: .