Skip to content

Commit

Permalink
add support for archiving pipelines
Browse files Browse the repository at this point in the history
adds functionality in fly and api for archiving and unarchiving
pipelines, in support of concoursegh-2518.

replicates:
vmware-archive/go-concourse#17
vmware-archive/fly#258
vmware-archive/atc#300
  • Loading branch information
Tyler Kellen committed Sep 25, 2018
1 parent 4c773bc commit 0072076
Show file tree
Hide file tree
Showing 20 changed files with 391 additions and 13 deletions.
12 changes: 7 additions & 5 deletions atc/api/accessor/accessorfakes/fake_access_factory.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions atc/api/handler.go
Expand Up @@ -134,6 +134,8 @@ func NewHandler(
atc.UnpausePipeline: pipelineHandlerFactory.HandlerFor(pipelineServer.UnpausePipeline),
atc.ExposePipeline: pipelineHandlerFactory.HandlerFor(pipelineServer.ExposePipeline),
atc.HidePipeline: pipelineHandlerFactory.HandlerFor(pipelineServer.HidePipeline),
atc.ArchivePipeline: pipelineHandlerFactory.HandlerFor(pipelineServer.ArchivePipeline),
atc.UnarchivePipeline: pipelineHandlerFactory.HandlerFor(pipelineServer.UnarchivePipeline),
atc.GetVersionsDB: pipelineHandlerFactory.HandlerFor(pipelineServer.GetVersionsDB),
atc.RenamePipeline: pipelineHandlerFactory.HandlerFor(pipelineServer.RenamePipeline),
atc.ListPipelineBuilds: pipelineHandlerFactory.HandlerFor(pipelineServer.ListPipelineBuilds),
Expand Down
21 changes: 21 additions & 0 deletions atc/api/pipelineserver/archive.go
@@ -0,0 +1,21 @@
package pipelineserver

import (
"net/http"

"github.com/concourse/concourse/atc/db"
)

func (s *Server) ArchivePipeline(pipelineDB db.Pipeline) http.Handler {
logger := s.logger.Session("archive-pipeline")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := pipelineDB.Archive()
if err != nil {
logger.Error("failed-to-archive-pipeline", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
})
}
21 changes: 21 additions & 0 deletions atc/api/pipelineserver/unarchive.go
@@ -0,0 +1,21 @@
package pipelineserver

import (
"net/http"

"github.com/concourse/concourse/atc/db"
)

func (s *Server) UnarchivePipeline(pipelineDB db.Pipeline) http.Handler {
logger := s.logger.Session("unarchive-pipeline")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := pipelineDB.Unarchive()
if err != nil {
logger.Error("failed-to-unarchive-pipeline", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
})
}
1 change: 1 addition & 0 deletions atc/api/present/pipeline.go
Expand Up @@ -11,6 +11,7 @@ func Pipeline(savedPipeline db.Pipeline) atc.Pipeline {
Name: savedPipeline.Name(),
TeamName: savedPipeline.TeamName(),
Paused: savedPipeline.Paused(),
Archived: savedPipeline.Archived(),
Public: savedPipeline.Public(),
Groups: savedPipeline.Groups(),
}
Expand Down
@@ -0,0 +1,4 @@
BEGIN;
ALTER TABLE pipelines
DROP COLUMN archived;
COMMIT;
@@ -0,0 +1,4 @@
BEGIN;
ALTER TABLE pipelines
ADD COLUMN archived boolean NOT NULL DEFAULT false;
COMMIT;
30 changes: 29 additions & 1 deletion atc/db/pipeline.go
Expand Up @@ -40,6 +40,7 @@ type Pipeline interface {
ConfigVersion() ConfigVersion
Public() bool
Paused() bool
Archived() bool
ScopedName(string) string

CheckPaused() (bool, error)
Expand Down Expand Up @@ -101,6 +102,9 @@ type Pipeline interface {
Pause() error
Unpause() error

Archive() error
Unarchive() error

Destroy() error
Rename(string) error

Expand All @@ -116,6 +120,7 @@ type pipeline struct {
configVersion ConfigVersion
paused bool
public bool
archived bool

cacheIndex int
versionsDB *algorithm.VersionsDB
Expand All @@ -137,7 +142,8 @@ var pipelinesQuery = psql.Select(`
p.team_id,
t.name,
p.paused,
p.public
p.public,
p.archived
`).
From("pipelines p").
LeftJoin("teams t ON p.team_id = t.id")
Expand Down Expand Up @@ -179,11 +185,33 @@ func (p *pipeline) Groups() atc.GroupConfigs { return p.groups }
func (p *pipeline) ConfigVersion() ConfigVersion { return p.configVersion }
func (p *pipeline) Public() bool { return p.public }
func (p *pipeline) Paused() bool { return p.paused }
func (p *pipeline) Archived() bool { return p.archived }

func (p *pipeline) ScopedName(n string) string {
return p.name + ":" + n
}

func (p *pipeline) Archive() error {
_, err := psql.Update("pipelines").
Set("archived", true).
Where(sq.Eq{
"id": p.id,
}).
RunWith(p.conn).
Exec()
return err
}
func (p *pipeline) Unarchive() error {
_, err := psql.Update("pipelines").
Set("archived", false).
Where(sq.Eq{
"id": p.id,
}).
RunWith(p.conn).
Exec()
return err
}

func (p *pipeline) Causality(versionedResourceID int) ([]Cause, error) {
rows, err := p.conn.Query(`
WITH RECURSIVE causality(versioned_resource_id, build_id) AS (
Expand Down
34 changes: 34 additions & 0 deletions atc/db/pipeline_test.go
Expand Up @@ -185,6 +185,40 @@ var _ = Describe("Pipeline", func() {
})
})

Describe("Archive", func() {
JustBeforeEach(func() {
Expect(pipeline.Archive()).To(Succeed())
found, err := pipeline.Reload()
Expect(err).ToNot(HaveOccurred())
Expect(found).To(BeTrue())
})
Context("when the pipeline is unarchived", func() {
BeforeEach(func() {
Expect(pipeline.Unarchive()).To(Succeed())
})
It("archives the pipeline", func() {
Expect(pipeline.Archived()).To(BeTrue())
})
})
})

Describe("Unarchive", func() {
JustBeforeEach(func() {
Expect(pipeline.Unarchive()).To(Succeed())
found, err := pipeline.Reload()
Expect(err).ToNot(HaveOccurred())
Expect(found).To(BeTrue())
})
Context("when the pipeline is archived", func() {
BeforeEach(func() {
Expect(pipeline.Archive()).To(Succeed())
})
It("unarchives the pipeline", func() {
Expect(pipeline.Archived()).To(BeFalse())
})
})
})

Describe("Rename", func() {
JustBeforeEach(func() {
Expect(pipeline.Rename("oopsies")).To(Succeed())
Expand Down
2 changes: 1 addition & 1 deletion atc/db/team.go
Expand Up @@ -951,7 +951,7 @@ func (t *team) findContainer(whereClause sq.Sqlizer) (CreatingContainer, Created

func scanPipeline(p *pipeline, scan scannable) error {
var groups sql.NullString
err := scan.Scan(&p.id, &p.name, &groups, &p.configVersion, &p.teamID, &p.teamName, &p.paused, &p.public)
err := scan.Scan(&p.id, &p.name, &groups, &p.configVersion, &p.teamID, &p.teamName, &p.paused, &p.public, &p.archived)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions atc/pipeline.go
Expand Up @@ -5,6 +5,7 @@ type Pipeline struct {
Name string `json:"name"`
Paused bool `json:"paused"`
Public bool `json:"public"`
Archived bool `json:"archived"`
Groups GroupConfigs `json:"groups,omitempty"`
TeamName string `json:"team_name"`
}
Expand Down
4 changes: 4 additions & 0 deletions atc/routes.go
Expand Up @@ -55,6 +55,8 @@ const (
OrderPipelines = "OrderPipelines"
PausePipeline = "PausePipeline"
UnpausePipeline = "UnpausePipeline"
ArchivePipeline = "ArchivePipeline"
UnarchivePipeline = "UnarchivePipeline"
ExposePipeline = "ExposePipeline"
HidePipeline = "HidePipeline"
RenamePipeline = "RenamePipeline"
Expand Down Expand Up @@ -139,6 +141,8 @@ var Routes = rata.Routes([]rata.Route{
{Path: "/api/v1/teams/:team_name/pipelines/ordering", Method: "PUT", Name: OrderPipelines},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/pause", Method: "PUT", Name: PausePipeline},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/unpause", Method: "PUT", Name: UnpausePipeline},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/archive", Method: "PUT", Name: ArchivePipeline},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/unarchive", Method: "PUT", Name: UnarchivePipeline},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/expose", Method: "PUT", Name: ExposePipeline},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/hide", Method: "PUT", Name: HidePipeline},
{Path: "/api/v1/teams/:team_name/pipelines/:pipeline_name/versions-db", Method: "GET", Name: GetVersionsDB},
Expand Down
2 changes: 2 additions & 0 deletions atc/wrappa/api_auth_wrappa.go
Expand Up @@ -129,10 +129,12 @@ func (wrappa *APIAuthWrappa) Wrap(handlers rata.Handlers) rata.Handlers {
atc.OrderPipelines,
atc.PauseJob,
atc.PausePipeline,
atc.ArchivePipeline,
atc.PauseResource,
atc.RenamePipeline,
atc.UnpauseJob,
atc.UnpausePipeline,
atc.UnarchivePipeline,
atc.UnpauseResource,
atc.ExposePipeline,
atc.HidePipeline,
Expand Down
49 changes: 49 additions & 0 deletions fly/commands/archive_pipeline.go
@@ -0,0 +1,49 @@
package commands

import (
"fmt"

"github.com/concourse/concourse/fly/commands/internal/displayhelpers"
"github.com/concourse/concourse/fly/commands/internal/flaghelpers"
"github.com/concourse/concourse/fly/rc"
)

type ArchivePipelineCommand struct {
Pipeline flaghelpers.PipelineFlag `short:"p" long:"pipeline" required:"true" description:"Pipeline to archive"`
}

func (command *ArchivePipelineCommand) Validate() error {
return command.Pipeline.Validate()
}

func (command *ArchivePipelineCommand) Execute(args []string) error {
err := command.Validate()
if err != nil {
return err
}

pipelineName := string(command.Pipeline)

target, err := rc.LoadTarget(Fly.Target, Fly.Verbose)
if err != nil {
return err
}

err = target.Validate()
if err != nil {
return err
}

found, err := target.Team().ArchivePipeline(pipelineName)
if err != nil {
return err
}

if found {
fmt.Printf("archived '%s'\n", pipelineName)
} else {
displayhelpers.Failf("pipeline '%s' not found\n", pipelineName)
}

return nil
}
2 changes: 2 additions & 0 deletions fly/commands/fly.go
Expand Up @@ -42,6 +42,8 @@ type FlyCommand struct {
SetPipeline SetPipelineCommand `command:"set-pipeline" alias:"sp" description:"Create or update a pipeline's configuration"`
PausePipeline PausePipelineCommand `command:"pause-pipeline" alias:"pp" description:"Pause a pipeline"`
UnpausePipeline UnpausePipelineCommand `command:"unpause-pipeline" alias:"up" description:"Un-pause a pipeline"`
ArchivePipeline ArchivePipelineCommand `command:"archive-pipeline" alias:"ap" description:"Archive a pipeline"`
UnarchivePipeline UnarchivePipelineCommand `command:"unarchive-pipeline" alias:"uap" description:"Un-archive a pipeline"`
ExposePipeline ExposePipelineCommand `command:"expose-pipeline" alias:"ep" description:"Make a pipeline publicly viewable"`
HidePipeline HidePipelineCommand `command:"hide-pipeline" alias:"hp" description:"Hide a pipeline from the public"`
RenamePipeline RenamePipelineCommand `command:"rename-pipeline" alias:"rp" description:"Rename a pipeline"`
Expand Down
49 changes: 49 additions & 0 deletions fly/commands/unarchive_pipeline.go
@@ -0,0 +1,49 @@
package commands

import (
"fmt"

"github.com/concourse/concourse/fly/commands/internal/displayhelpers"
"github.com/concourse/concourse/fly/commands/internal/flaghelpers"
"github.com/concourse/concourse/fly/rc"
)

type UnarchivePipelineCommand struct {
Pipeline flaghelpers.PipelineFlag `short:"p" long:"pipeline" required:"true" description:"Pipeline to unarchive"`
}

func (command *UnarchivePipelineCommand) Validate() error {
return command.Pipeline.Validate()
}

func (command *UnarchivePipelineCommand) Execute(args []string) error {
err := command.Validate()
if err != nil {
return err
}

pipelineName := string(command.Pipeline)

target, err := rc.LoadTarget(Fly.Target, Fly.Verbose)
if err != nil {
return err
}

err = target.Validate()
if err != nil {
return err
}

found, err := target.Team().UnarchivePipeline(pipelineName)
if err != nil {
return err
}

if found {
fmt.Printf("unarchived '%s'\n", pipelineName)
} else {
displayhelpers.Failf("pipeline '%s' not found\n", pipelineName)
}

return nil
}

0 comments on commit 0072076

Please sign in to comment.