From 447741b840b921ac2f028e3148093a6216e754d0 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 10 May 2016 22:19:45 -0700 Subject: [PATCH] added query, endpoint, cli for build queue items --- client/client.go | 19 ++++++---- client/client_impl.go | 43 ++++++++++++--------- drone/agent/agent.go | 40 +++----------------- drone/agent/exec.go | 2 - drone/build.go | 1 + drone/build_queue.go | 60 ++++++++++++++++++++++++++++++ router/router.go | 10 +++++ server/build.go | 9 +++++ store/datastore/builds.go | 34 +++++++++++++++++ store/datastore/ddl/postgres/5.sql | 4 ++ store/datastore/ddl/sqlite3/5.sql | 4 ++ store/store.go | 7 ++++ 12 files changed, 172 insertions(+), 61 deletions(-) create mode 100644 drone/build_queue.go diff --git a/client/client.go b/client/client.go index 2def55413..06155cc7c 100644 --- a/client/client.go +++ b/client/client.go @@ -33,8 +33,8 @@ type Client interface { // Repo returns a repository by name. Repo(string, string) (*model.Repo, error) - // RepoList returns a list of all repositories to which - // the user has explicit access in the host system. + // RepoList returns a list of all repositories to which the user has explicit + // access in the host system. RepoList() ([]*model.Repo, error) // RepoPost activates a repository. @@ -58,29 +58,32 @@ type Client interface { // Build returns a repository build by number. Build(string, string, int) (*model.Build, error) - // BuildLast returns the latest repository build by branch. - // An empty branch will result in the default branch. + // BuildLast returns the latest repository build by branch. An empty branch + // will result in the default branch. BuildLast(string, string, string) (*model.Build, error) // BuildList returns a list of recent builds for the // the specified repository. BuildList(string, string) ([]*model.Build, error) + // BuildQueue returns a list of enqueued builds. + BuildQueue() ([]*model.Feed, error) + // BuildStart re-starts a stopped build. BuildStart(string, string, int) (*model.Build, error) // BuildStop stops the specified running job for given build. BuildStop(string, string, int, int) error - // BuildFork re-starts a stopped build with a new build number, - // preserving the prior history. + // BuildFork re-starts a stopped build with a new build number, preserving + // the prior history. BuildFork(string, string, int) (*model.Build, error) // BuildLogs returns the build logs for the specified job. BuildLogs(string, string, int, int) (io.ReadCloser, error) - // Deploy triggers a deployment for an existing build using the - // specified target environment. + // Deploy triggers a deployment for an existing build using the specified + // target environment. Deploy(string, string, int, string) (*model.Build, error) // diff --git a/client/client_impl.go b/client/client_impl.go index 3b40b9e19..c75d1631a 100644 --- a/client/client_impl.go +++ b/client/client_impl.go @@ -24,23 +24,24 @@ const ( pathStream = "%s/api/queue/stream/%d" pathPush = "%s/api/queue/status/%d" - pathSelf = "%s/api/user" - pathFeed = "%s/api/user/feed" - pathRepos = "%s/api/user/repos" - pathRepo = "%s/api/repos/%s/%s" - pathEncrypt = "%s/api/repos/%s/%s/encrypt" - pathBuilds = "%s/api/repos/%s/%s/builds" - pathBuild = "%s/api/repos/%s/%s/builds/%v" - pathJob = "%s/api/repos/%s/%s/builds/%d/%d" - pathLog = "%s/api/repos/%s/%s/logs/%d/%d" - pathKey = "%s/api/repos/%s/%s/key" - pathSign = "%s/api/repos/%s/%s/sign" - pathSecrets = "%s/api/repos/%s/%s/secrets" - pathSecret = "%s/api/repos/%s/%s/secrets/%s" - pathNodes = "%s/api/nodes" - pathNode = "%s/api/nodes/%d" - pathUsers = "%s/api/users" - pathUser = "%s/api/users/%s" + pathSelf = "%s/api/user" + pathFeed = "%s/api/user/feed" + pathRepos = "%s/api/user/repos" + pathRepo = "%s/api/repos/%s/%s" + pathEncrypt = "%s/api/repos/%s/%s/encrypt" + pathBuilds = "%s/api/repos/%s/%s/builds" + pathBuild = "%s/api/repos/%s/%s/builds/%v" + pathJob = "%s/api/repos/%s/%s/builds/%d/%d" + pathLog = "%s/api/repos/%s/%s/logs/%d/%d" + pathKey = "%s/api/repos/%s/%s/key" + pathSign = "%s/api/repos/%s/%s/sign" + pathSecrets = "%s/api/repos/%s/%s/secrets" + pathSecret = "%s/api/repos/%s/%s/secrets/%s" + pathNodes = "%s/api/nodes" + pathNode = "%s/api/nodes/%d" + pathUsers = "%s/api/users" + pathUser = "%s/api/users/%s" + pathBuildQueue = "%s/api/builds" ) type client struct { @@ -189,6 +190,14 @@ func (c *client) BuildList(owner, name string) ([]*model.Build, error) { return out, err } +// BuildQueue returns a list of enqueued builds. +func (c *client) BuildQueue() ([]*model.Feed, error) { + var out []*model.Feed + uri := fmt.Sprintf(pathBuildQueue, c.base) + err := c.get(uri, &out) + return out, err +} + // BuildStart re-starts a stopped build. func (c *client) BuildStart(owner, name string, num int) (*model.Build, error) { out := new(model.Build) diff --git a/drone/agent/agent.go b/drone/agent/agent.go index 32405a3e6..45e47ed35 100644 --- a/drone/agent/agent.go +++ b/drone/agent/agent.go @@ -53,8 +53,8 @@ var AgentCmd = cli.Command{ Value: "amd64", }, cli.StringFlag{ - EnvVar: "DOCKER_STORAGE_DRIVER", - Name: "docker-storage-driver", + EnvVar: "DRONE_STORAGE_DRIVER", + Name: "drone-storage-driver", Usage: "docker storage driver", Value: "overlay", }, @@ -80,26 +80,6 @@ var AgentCmd = cli.Command{ Name: "debug", Usage: "start the agent in debug mode", }, - cli.BoolFlag{ - EnvVar: "DRONE_EXPERIMENTAL", - Name: "experimental", - Usage: "start the agent with experimental features", - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_PLUGIN_NETRC", - Name: "netrc-plugin", - Usage: "plugins that receive the netrc file", - Value: &cli.StringSlice{ - "git", - "git:*", - "hg", - "hg:*", - "plugins/hg", - "plugins/hg:*", - "plugins/git", - "plugins/git:*", - }, - }, cli.StringSliceFlag{ EnvVar: "DRONE_PLUGIN_PRIVILEGED", Name: "privileged", @@ -113,22 +93,16 @@ var AgentCmd = cli.Command{ "plugins/ecr:*", }, }, - cli.BoolFlag{ - EnvVar: "DRONE_PLUGIN_PULL", - Name: "pull", - Usage: "always pull latest plugin images", - }, cli.StringFlag{ EnvVar: "DRONE_PLUGIN_NAMESPACE", Name: "namespace", Value: "plugins", Usage: "default plugin image namespace", }, - cli.StringSliceFlag{ - EnvVar: "DRONE_PLUGIN_WHITELIST", - Name: "whitelist", - Usage: "plugins that are permitted to run on the host", - Value: &cli.StringSlice{"plugins/*"}, + cli.BoolFlag{ + EnvVar: "DRONE_PLUGIN_PULL", + Name: "pull", + Usage: "always pull latest plugin images", }, }, } @@ -168,10 +142,8 @@ func start(c *cli.Context) { drone: client, docker: docker, config: config{ - whitelist: c.StringSlice("whitelist"), namespace: c.String("namespace"), privileged: c.StringSlice("privileged"), - netrc: c.StringSlice("netrc-plugin"), pull: c.Bool("pull"), }, } diff --git a/drone/agent/exec.go b/drone/agent/exec.go index 1df73378e..42b54cc97 100644 --- a/drone/agent/exec.go +++ b/drone/agent/exec.go @@ -15,9 +15,7 @@ import ( type config struct { platform string namespace string - whitelist []string privileged []string - netrc []string pull bool } diff --git a/drone/build.go b/drone/build.go index 534fef1b7..716056968 100644 --- a/drone/build.go +++ b/drone/build.go @@ -11,5 +11,6 @@ var buildCmd = cli.Command{ buildInfoCmd, buildStopCmd, buildStartCmd, + buildQueueCmd, }, } diff --git a/drone/build_queue.go b/drone/build_queue.go new file mode 100644 index 000000000..e67f80297 --- /dev/null +++ b/drone/build_queue.go @@ -0,0 +1,60 @@ +package main + +import ( + "log" + "os" + "text/template" + + "github.com/codegangsta/cli" +) + +var buildQueueCmd = cli.Command{ + Name: "queue", + Usage: "show build queue", + Action: func(c *cli.Context) { + if err := buildQueue(c); err != nil { + log.Fatalln(err) + } + }, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "format", + Usage: "format output", + Value: tmplBuildQueue, + }, + }, +} + +func buildQueue(c *cli.Context) error { + + client, err := newClient(c) + if err != nil { + return err + } + + builds, err := client.BuildQueue() + if err != nil { + return err + } + + tmpl, err := template.New("_").Parse(c.String("format") + "\n") + if err != nil { + return err + } + + for _, build := range builds { + tmpl.Execute(os.Stdout, build) + } + return nil +} + +// template for build list information +var tmplBuildQueue = "\x1b[33m{{ .FullName }} #{{ .Number }} \x1b[0m" + ` +Status: {{ .Status }} +Event: {{ .Event }} +Commit: {{ .Commit }} +Branch: {{ .Branch }} +Ref: {{ .Ref }} +Author: {{ .Author }} {{ if .Email }}<{{.Email}}>{{ end }} +Message: {{ .Message }} +` diff --git a/router/router.go b/router/router.go index 3c4a7a44d..7fd88ba09 100644 --- a/router/router.go +++ b/router/router.go @@ -135,6 +135,16 @@ func Load(middleware ...gin.HandlerFunc) http.Handler { auth.POST("/token", server.GetLoginToken) } + builds := e.Group("/api/builds") + { + builds.Use(session.MustAdmin()) + builds.GET("", server.GetBuildQueue) + } + + // agents := e.Group("/api/agents") { + // builds.Use(session.MustAdmin, server.GetAgents) + // } + queue := e.Group("/api/queue") { queue.Use(session.AuthorizeAgent) diff --git a/server/build.go b/server/build.go index 1d75fd4df..c996a9f67 100644 --- a/server/build.go +++ b/server/build.go @@ -305,3 +305,12 @@ func PostBuild(c *gin.Context) { }) } } + +func GetBuildQueue(c *gin.Context) { + out, err := store.GetBuildQueue(c) + if err != nil { + c.String(500, "Error getting build queue. %s", err) + return + } + c.JSON(200, out) +} diff --git a/store/datastore/builds.go b/store/datastore/builds.go index a8ac24bd9..0f03608cb 100644 --- a/store/datastore/builds.go +++ b/store/datastore/builds.go @@ -49,6 +49,12 @@ func (db *datastore) GetBuildList(repo *model.Repo) ([]*model.Build, error) { return builds, err } +func (db *datastore) GetBuildQueue() ([]*model.Feed, error) { + feed := []*model.Feed{} + err := meddler.QueryAll(db, &feed, buildQueueList) + return feed, err +} + func (db *datastore) CreateBuild(build *model.Build, jobs ...*model.Job) error { var number int db.QueryRow(rebind(buildNumberLast), build.RepoID).Scan(&number) @@ -135,3 +141,31 @@ SELECT MAX(build_number) FROM builds WHERE build_repo_id = ? ` + +const buildQueueList = ` +SELECT + repo_owner +,repo_name +,repo_full_name +,build_number +,build_event +,build_status +,build_created +,build_started +,build_finished +,build_commit +,build_branch +,build_ref +,build_refspec +,build_remote +,build_title +,build_message +,build_author +,build_email +,build_avatar +FROM + builds b +,repos r +WHERE b.build_repo_id = r.repo_id + AND b.build_status IN ('pending','running') +` diff --git a/store/datastore/ddl/postgres/5.sql b/store/datastore/ddl/postgres/5.sql index 2f4702379..8265a9857 100644 --- a/store/datastore/ddl/postgres/5.sql +++ b/store/datastore/ddl/postgres/5.sql @@ -6,7 +6,11 @@ ALTER TABLE builds ADD COLUMN build_verified BOOLEAN; UPDATE builds SET build_signed = false; UPDATE builds SET build_verified = false; +CREATE INDEX ix_build_status_running ON builds (build_status) + WHERE build_status IN ('pending', 'running'); + -- +migrate Down ALTER TABLE builds DROP COLUMN build_signed; ALTER TABLE builds DROP COLUMN build_verified; +DROP INDEX ix_build_status_running; diff --git a/store/datastore/ddl/sqlite3/5.sql b/store/datastore/ddl/sqlite3/5.sql index 699b26895..21e97c3b0 100644 --- a/store/datastore/ddl/sqlite3/5.sql +++ b/store/datastore/ddl/sqlite3/5.sql @@ -6,7 +6,11 @@ ALTER TABLE builds ADD COLUMN build_verified BOOLEAN; UPDATE builds SET build_signed = 0; UPDATE builds SET build_verified = 0; +CREATE INDEX ix_build_status_running ON builds (build_status) + WHERE build_status IN ('pending', 'running'); + -- +migrate Down ALTER TABLE builds DROP COLUMN build_signed; ALTER TABLE builds DROP COLUMN build_verified; +DROP INDEX ix_build_status_running; diff --git a/store/store.go b/store/store.go index 2d20380aa..e798a8715 100644 --- a/store/store.go +++ b/store/store.go @@ -87,6 +87,9 @@ type Store interface { // GetBuildList gets a list of builds for the repository GetBuildList(*model.Repo) ([]*model.Build, error) + // GetBuildQueue gets a list of build in queue. + GetBuildQueue() ([]*model.Feed, error) + // CreateBuild creates a new build and jobs. CreateBuild(*model.Build, ...*model.Job) error @@ -224,6 +227,10 @@ func GetBuildList(c context.Context, repo *model.Repo) ([]*model.Build, error) { return FromContext(c).GetBuildList(repo) } +func GetBuildQueue(c context.Context) ([]*model.Feed, error) { + return FromContext(c).GetBuildQueue() +} + func CreateBuild(c context.Context, build *model.Build, jobs ...*model.Job) error { return FromContext(c).CreateBuild(build, jobs...) }