mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-30 05:41:12 +00:00
Merge pull request #1992 from bradrydzewski/feature/steps
add registry management
This commit is contained in:
commit
7a98bf5398
24 changed files with 948 additions and 412 deletions
|
@ -117,4 +117,19 @@ type Client interface {
|
||||||
|
|
||||||
// AgentList returns a list of build agents.
|
// AgentList returns a list of build agents.
|
||||||
AgentList() ([]*model.Agent, error)
|
AgentList() ([]*model.Agent, error)
|
||||||
|
|
||||||
|
// Registry returns a registry by hostname.
|
||||||
|
Registry(owner, name, hostname string) (*model.Registry, error)
|
||||||
|
|
||||||
|
// RegistryList returns a list of all repository registries.
|
||||||
|
RegistryList(owner, name string) ([]*model.Registry, error)
|
||||||
|
|
||||||
|
// RegistryCreate creates a registry.
|
||||||
|
RegistryCreate(owner, name string, registry *model.Registry) (*model.Registry, error)
|
||||||
|
|
||||||
|
// RegistryUpdate updates a registry.
|
||||||
|
RegistryUpdate(owner, name string, registry *model.Registry) (*model.Registry, error)
|
||||||
|
|
||||||
|
// RegistryDelete deletes a registry.
|
||||||
|
RegistryDelete(owner, name, hostname string) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,32 +26,34 @@ const (
|
||||||
pathLogs = "%s/api/queue/logs/%d"
|
pathLogs = "%s/api/queue/logs/%d"
|
||||||
pathLogsAuth = "%s/api/queue/logs/%d?access_token=%s"
|
pathLogsAuth = "%s/api/queue/logs/%d?access_token=%s"
|
||||||
|
|
||||||
pathSelf = "%s/api/user"
|
pathSelf = "%s/api/user"
|
||||||
pathFeed = "%s/api/user/feed"
|
pathFeed = "%s/api/user/feed"
|
||||||
pathRepos = "%s/api/user/repos"
|
pathRepos = "%s/api/user/repos"
|
||||||
pathRepo = "%s/api/repos/%s/%s"
|
pathRepo = "%s/api/repos/%s/%s"
|
||||||
pathChown = "%s/api/repos/%s/%s/chown"
|
pathChown = "%s/api/repos/%s/%s/chown"
|
||||||
pathEncrypt = "%s/api/repos/%s/%s/encrypt"
|
pathEncrypt = "%s/api/repos/%s/%s/encrypt"
|
||||||
pathBuilds = "%s/api/repos/%s/%s/builds"
|
pathBuilds = "%s/api/repos/%s/%s/builds"
|
||||||
pathBuild = "%s/api/repos/%s/%s/builds/%v"
|
pathBuild = "%s/api/repos/%s/%s/builds/%v"
|
||||||
pathApprove = "%s/api/repos/%s/%s/builds/%d/approve"
|
pathApprove = "%s/api/repos/%s/%s/builds/%d/approve"
|
||||||
pathDecline = "%s/api/repos/%s/%s/builds/%d/decline"
|
pathDecline = "%s/api/repos/%s/%s/builds/%d/decline"
|
||||||
pathJob = "%s/api/repos/%s/%s/builds/%d/%d"
|
pathJob = "%s/api/repos/%s/%s/builds/%d/%d"
|
||||||
pathLog = "%s/api/repos/%s/%s/logs/%d/%d"
|
pathLog = "%s/api/repos/%s/%s/logs/%d/%d"
|
||||||
pathKey = "%s/api/repos/%s/%s/key"
|
pathKey = "%s/api/repos/%s/%s/key"
|
||||||
pathSign = "%s/api/repos/%s/%s/sign"
|
pathSign = "%s/api/repos/%s/%s/sign"
|
||||||
pathRepoSecrets = "%s/api/repos/%s/%s/secrets"
|
pathRepoSecrets = "%s/api/repos/%s/%s/secrets"
|
||||||
pathRepoSecret = "%s/api/repos/%s/%s/secrets/%s"
|
pathRepoSecret = "%s/api/repos/%s/%s/secrets/%s"
|
||||||
pathTeamSecrets = "%s/api/teams/%s/secrets"
|
pathRepoRegistries = "%s/api/repos/%s/%s/registry"
|
||||||
pathTeamSecret = "%s/api/teams/%s/secrets/%s"
|
pathRepoRegistry = "%s/api/repos/%s/%s/registry/%s"
|
||||||
pathGlobalSecrets = "%s/api/global/secrets"
|
pathTeamSecrets = "%s/api/teams/%s/secrets"
|
||||||
pathGlobalSecret = "%s/api/global/secrets/%s"
|
pathTeamSecret = "%s/api/teams/%s/secrets/%s"
|
||||||
pathNodes = "%s/api/nodes"
|
pathGlobalSecrets = "%s/api/global/secrets"
|
||||||
pathNode = "%s/api/nodes/%d"
|
pathGlobalSecret = "%s/api/global/secrets/%s"
|
||||||
pathUsers = "%s/api/users"
|
pathNodes = "%s/api/nodes"
|
||||||
pathUser = "%s/api/users/%s"
|
pathNode = "%s/api/nodes/%d"
|
||||||
pathBuildQueue = "%s/api/builds"
|
pathUsers = "%s/api/users"
|
||||||
pathAgent = "%s/api/agents"
|
pathUser = "%s/api/users/%s"
|
||||||
|
pathBuildQueue = "%s/api/builds"
|
||||||
|
pathAgent = "%s/api/agents"
|
||||||
)
|
)
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
@ -373,6 +375,44 @@ func (c *client) AgentList() ([]*model.Agent, error) {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Registry returns a registry by hostname.
|
||||||
|
func (c *client) Registry(owner, name, hostname string) (*model.Registry, error) {
|
||||||
|
out := new(model.Registry)
|
||||||
|
uri := fmt.Sprintf(pathRepoRegistry, c.base, owner, name, hostname)
|
||||||
|
err := c.get(uri, out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryList returns a list of all repository registries.
|
||||||
|
func (c *client) RegistryList(owner string, name string) ([]*model.Registry, error) {
|
||||||
|
var out []*model.Registry
|
||||||
|
uri := fmt.Sprintf(pathRepoRegistries, c.base, owner, name)
|
||||||
|
err := c.get(uri, &out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryCreate creates a registry.
|
||||||
|
func (c *client) RegistryCreate(owner, name string, in *model.Registry) (*model.Registry, error) {
|
||||||
|
out := new(model.Registry)
|
||||||
|
uri := fmt.Sprintf(pathRepoRegistries, c.base, owner, name)
|
||||||
|
err := c.post(uri, in, out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryUpdate updates a registry.
|
||||||
|
func (c *client) RegistryUpdate(owner, name string, in *model.Registry) (*model.Registry, error) {
|
||||||
|
out := new(model.Registry)
|
||||||
|
uri := fmt.Sprintf(pathRepoRegistry, c.base, owner, name, in.Address)
|
||||||
|
err := c.patch(uri, in, out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryDelete deletes a registry.
|
||||||
|
func (c *client) RegistryDelete(owner, name, hostname string) error {
|
||||||
|
uri := fmt.Sprintf(pathRepoRegistry, c.base, owner, name, hostname)
|
||||||
|
return c.delete(uri)
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// http request helper functions
|
// http request helper functions
|
||||||
//
|
//
|
||||||
|
|
|
@ -37,6 +37,7 @@ func main() {
|
||||||
deployCmd,
|
deployCmd,
|
||||||
execCmd,
|
execCmd,
|
||||||
infoCmd,
|
infoCmd,
|
||||||
|
registryCmd,
|
||||||
secretCmd,
|
secretCmd,
|
||||||
serverCmd,
|
serverCmd,
|
||||||
signCmd,
|
signCmd,
|
||||||
|
|
15
drone/registry.go
Normal file
15
drone/registry.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/urfave/cli"
|
||||||
|
|
||||||
|
var registryCmd = cli.Command{
|
||||||
|
Name: "registry",
|
||||||
|
Usage: "manage registries",
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
registryCreateCmd,
|
||||||
|
registryDeleteCmd,
|
||||||
|
registryUpdateCmd,
|
||||||
|
registryInfoCmd,
|
||||||
|
registryListCmd,
|
||||||
|
},
|
||||||
|
}
|
61
drone/registry_add.go
Normal file
61
drone/registry_add.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var registryCreateCmd = cli.Command{
|
||||||
|
Name: "add",
|
||||||
|
Usage: "adds a registry",
|
||||||
|
Action: registryCreate,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "repository",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "hostname",
|
||||||
|
Usage: "registry hostname",
|
||||||
|
Value: "index.docker.io",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "username",
|
||||||
|
Usage: "registry username",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "password",
|
||||||
|
Usage: "registry password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func registryCreate(c *cli.Context) error {
|
||||||
|
var (
|
||||||
|
hostname = c.String("hostname")
|
||||||
|
username = c.String("username")
|
||||||
|
password = c.String("password")
|
||||||
|
reponame = c.String("repository")
|
||||||
|
)
|
||||||
|
if reponame == "" {
|
||||||
|
reponame = c.Args().First()
|
||||||
|
}
|
||||||
|
owner, name, err := parseRepo(reponame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
registry := &model.Registry{
|
||||||
|
Address: hostname,
|
||||||
|
Username: username,
|
||||||
|
Password: password,
|
||||||
|
}
|
||||||
|
_, err = client.RegistryCreate(owner, name, registry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
59
drone/registry_info.go
Normal file
59
drone/registry_info.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var registryInfoCmd = cli.Command{
|
||||||
|
Name: "info",
|
||||||
|
Usage: "display registry info",
|
||||||
|
Action: registryInfo,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "repository",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "hostname",
|
||||||
|
Usage: "registry hostname",
|
||||||
|
Value: "index.docker.io",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "format",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
Value: tmplRegistryList,
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func registryInfo(c *cli.Context) error {
|
||||||
|
var (
|
||||||
|
hostname = c.String("hostname")
|
||||||
|
reponame = c.String("repository")
|
||||||
|
format = c.String("format") + "\n"
|
||||||
|
)
|
||||||
|
if reponame == "" {
|
||||||
|
reponame = c.Args().First()
|
||||||
|
}
|
||||||
|
owner, name, err := parseRepo(reponame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
registry, err := client.Registry(owner, name, hostname)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("_").Parse(format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return tmpl.Execute(os.Stdout, registry)
|
||||||
|
}
|
63
drone/registry_list.go
Normal file
63
drone/registry_list.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var registryListCmd = cli.Command{
|
||||||
|
Name: "ls",
|
||||||
|
Usage: "list regitries",
|
||||||
|
Action: registryList,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "repository",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "format",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
Value: tmplRegistryList,
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func registryList(c *cli.Context) error {
|
||||||
|
var (
|
||||||
|
format = c.String("format") + "\n"
|
||||||
|
reponame = c.String("repository")
|
||||||
|
)
|
||||||
|
if reponame == "" {
|
||||||
|
reponame = c.Args().First()
|
||||||
|
}
|
||||||
|
owner, name, err := parseRepo(reponame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
list, err := client.RegistryList(owner, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("_").Parse(format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, registry := range list {
|
||||||
|
tmpl.Execute(os.Stdout, registry)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// template for build list information
|
||||||
|
var tmplRegistryList = "\x1b[33m{{ .Address }} \x1b[0m" + `
|
||||||
|
Username: {{ .Username }}
|
||||||
|
Password: ********
|
||||||
|
Email: {{ .Email }}
|
||||||
|
`
|
39
drone/registry_rm.go
Normal file
39
drone/registry_rm.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/urfave/cli"
|
||||||
|
|
||||||
|
var registryDeleteCmd = cli.Command{
|
||||||
|
Name: "rm",
|
||||||
|
Usage: "remove a registry",
|
||||||
|
Action: registryDelete,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "repository",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "hostname",
|
||||||
|
Usage: "registry hostname",
|
||||||
|
Value: "index.docker.io",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func registryDelete(c *cli.Context) error {
|
||||||
|
var (
|
||||||
|
hostname = c.String("hostname")
|
||||||
|
reponame = c.String("repository")
|
||||||
|
)
|
||||||
|
if reponame == "" {
|
||||||
|
reponame = c.Args().First()
|
||||||
|
}
|
||||||
|
owner, name, err := parseRepo(reponame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return client.RegistryDelete(owner, name, hostname)
|
||||||
|
}
|
61
drone/registry_set.go
Normal file
61
drone/registry_set.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var registryUpdateCmd = cli.Command{
|
||||||
|
Name: "update",
|
||||||
|
Usage: "update a registry",
|
||||||
|
Action: registryUpdate,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "repository",
|
||||||
|
Usage: "repository name (e.g. octocat/hello-world)",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "hostname",
|
||||||
|
Usage: "registry hostname",
|
||||||
|
Value: "index.docker.io",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "username",
|
||||||
|
Usage: "registry username",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "password",
|
||||||
|
Usage: "registry password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func registryUpdate(c *cli.Context) error {
|
||||||
|
var (
|
||||||
|
hostname = c.String("hostname")
|
||||||
|
username = c.String("username")
|
||||||
|
password = c.String("password")
|
||||||
|
reponame = c.String("repository")
|
||||||
|
)
|
||||||
|
if reponame == "" {
|
||||||
|
reponame = c.Args().First()
|
||||||
|
}
|
||||||
|
owner, name, err := parseRepo(reponame)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
registry := &model.Registry{
|
||||||
|
Address: hostname,
|
||||||
|
Username: username,
|
||||||
|
Password: password,
|
||||||
|
}
|
||||||
|
_, err = client.RegistryUpdate(owner, name, registry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
23
model/limit.go
Normal file
23
model/limit.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
// Limiter defines an interface for limiting repository creation.
|
||||||
|
// This could be used, for example, to limit repository creation to
|
||||||
|
// a specific organization or a specific set of users.
|
||||||
|
type Limiter interface {
|
||||||
|
LimitUser(*User) error
|
||||||
|
LimitRepo(*User, *Repo) error
|
||||||
|
LimitBuild(*User, *Repo, *Build) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoLimit impliments the Limiter interface without enforcing any
|
||||||
|
// actual limits. All limiting functions are no-ops.
|
||||||
|
type NoLimit struct{}
|
||||||
|
|
||||||
|
// LimitUser is a no-op for limiting user creation.
|
||||||
|
func (NoLimit) LimitUser(*User) error { return nil }
|
||||||
|
|
||||||
|
// LimitRepo is a no-op for limiting repo creation.
|
||||||
|
func (NoLimit) LimitRepo(*User, *Repo) error { return nil }
|
||||||
|
|
||||||
|
// LimitBuild is a no-op for limiting build creation.
|
||||||
|
func (NoLimit) LimitBuild(*User, *Repo, *Build) error { return nil }
|
|
@ -1,15 +1,56 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
errRegistryAddressInvalid = errors.New("Invalid Registry Address")
|
||||||
|
errRegistryUsernameInvalid = errors.New("Invalid Registry Username")
|
||||||
|
errRegistryPasswordInvalid = errors.New("Invalid Registry Password")
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegistryStore persists registry information to storage.
|
||||||
|
type RegistryStore interface {
|
||||||
|
RegistryFind(*Repo, string) (*Registry, error)
|
||||||
|
RegistryList(*Repo) ([]*Registry, error)
|
||||||
|
RegistryCreate(*Registry) error
|
||||||
|
RegistryUpdate(*Registry) error
|
||||||
|
RegistryDelete(*Registry) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registry represents a docker registry with credentials.
|
||||||
|
// swagger:model registry
|
||||||
type Registry struct {
|
type Registry struct {
|
||||||
ID int64 `json:"id" meddler:"registry_id,pk"`
|
ID int64 `json:"id" meddler:"registry_id,pk"`
|
||||||
RepoID int64 `json:"-" meddler:"registry_repo_id"`
|
RepoID int64 `json:"-" meddler:"registry_repo_id"`
|
||||||
Addr string `json:"addr" meddler:"registry_addr"`
|
Address string `json:"address" meddler:"registry_addr"`
|
||||||
Username string `json:"username" meddler:"registry_username"`
|
Username string `json:"username" meddler:"registry_username"`
|
||||||
Password string `json:"password" meddler:"registry_password"`
|
Password string `json:"password" meddler:"registry_password"`
|
||||||
Email string `json:"email" meddler:"registry_email"`
|
Email string `json:"email" meddler:"registry_email"`
|
||||||
Token string `json:"token" meddler:"registry_token"`
|
Token string `json:"token" meddler:"registry_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate validates the registry information.
|
||||||
func (r *Registry) Validate() error {
|
func (r *Registry) Validate() error {
|
||||||
return nil
|
switch {
|
||||||
|
case len(r.Address) == 0:
|
||||||
|
return errRegistryAddressInvalid
|
||||||
|
case len(r.Username) == 0:
|
||||||
|
return errRegistryUsernameInvalid
|
||||||
|
case len(r.Password) == 0:
|
||||||
|
return errRegistryPasswordInvalid
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy makes a copy of the registry without the password.
|
||||||
|
func (r *Registry) Copy() *Registry {
|
||||||
|
return &Registry{
|
||||||
|
ID: r.ID,
|
||||||
|
RepoID: r.RepoID,
|
||||||
|
Address: r.Address,
|
||||||
|
Username: r.Username,
|
||||||
|
Email: r.Email,
|
||||||
|
Token: r.Token,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,13 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
||||||
repo.POST("/secrets", session.MustPush, server.PostSecret)
|
repo.POST("/secrets", session.MustPush, server.PostSecret)
|
||||||
repo.DELETE("/secrets/:secret", session.MustPush, server.DeleteSecret)
|
repo.DELETE("/secrets/:secret", session.MustPush, server.DeleteSecret)
|
||||||
|
|
||||||
|
// requires push permissions
|
||||||
|
repo.GET("/registry", session.MustPush, server.GetRegistryList)
|
||||||
|
repo.POST("/registry", session.MustPush, server.PostRegistry)
|
||||||
|
repo.GET("/registry/:address", session.MustPush, server.GetRegistry)
|
||||||
|
repo.PATCH("/registry/:address", session.MustPush, server.PatchRegistry)
|
||||||
|
repo.DELETE("/registry/:address", session.MustPush, server.DeleteRegistry)
|
||||||
|
|
||||||
// requires push permissions
|
// requires push permissions
|
||||||
repo.PATCH("", session.MustPush, server.PatchRepo)
|
repo.PATCH("", session.MustPush, server.PatchRepo)
|
||||||
repo.DELETE("", session.MustRepoAdmin(), server.DeleteRepo)
|
repo.DELETE("", session.MustRepoAdmin(), server.DeleteRepo)
|
||||||
|
|
133
server/registry.go
Normal file
133
server/registry.go
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/drone/drone/router/middleware/session"
|
||||||
|
"github.com/drone/drone/store"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRegistry gets the name registry from the database and writes
|
||||||
|
// to the response in json format.
|
||||||
|
func GetRegistry(c *gin.Context) {
|
||||||
|
var (
|
||||||
|
repo = session.Repo(c)
|
||||||
|
name = c.Param("registry")
|
||||||
|
)
|
||||||
|
registry, err := store.FromContext(c).RegistryFind(repo, name)
|
||||||
|
if err != nil {
|
||||||
|
c.String(404, "Error getting registry %q. %s", name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, registry.Copy())
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostRegistry persists the registry to the database.
|
||||||
|
func PostRegistry(c *gin.Context) {
|
||||||
|
repo := session.Repo(c)
|
||||||
|
|
||||||
|
in := new(model.Registry)
|
||||||
|
if err := c.Bind(in); err != nil {
|
||||||
|
c.String(http.StatusBadRequest, "Error parsing request. %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
registry := &model.Registry{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Address: in.Address,
|
||||||
|
Username: in.Username,
|
||||||
|
Password: in.Password,
|
||||||
|
Token: in.Token,
|
||||||
|
Email: in.Email,
|
||||||
|
}
|
||||||
|
if err := registry.Validate(); err != nil {
|
||||||
|
c.String(400, "Error inserting registry. %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := store.FromContext(c).RegistryCreate(registry); err != nil {
|
||||||
|
c.String(500, "Error inserting registry %q. %s", in.Address, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, in.Copy())
|
||||||
|
}
|
||||||
|
|
||||||
|
// PatchRegistry updates the registry in the database.
|
||||||
|
func PatchRegistry(c *gin.Context) {
|
||||||
|
var (
|
||||||
|
repo = session.Repo(c)
|
||||||
|
name = c.Param("registry")
|
||||||
|
)
|
||||||
|
|
||||||
|
in := new(model.Registry)
|
||||||
|
err := c.Bind(in)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusBadRequest, "Error parsing request. %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registry, err := store.FromContext(c).RegistryFind(repo, name)
|
||||||
|
if err != nil {
|
||||||
|
c.String(404, "Error getting registry %q. %s", name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if in.Username != "" {
|
||||||
|
registry.Username = in.Username
|
||||||
|
}
|
||||||
|
if in.Password != "" {
|
||||||
|
registry.Password = in.Password
|
||||||
|
}
|
||||||
|
if in.Token != "" {
|
||||||
|
registry.Token = in.Token
|
||||||
|
}
|
||||||
|
if in.Email != "" {
|
||||||
|
registry.Email = in.Email
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := registry.Validate(); err != nil {
|
||||||
|
c.String(400, "Error updating registry. %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := store.FromContext(c).RegistryUpdate(registry); err != nil {
|
||||||
|
c.String(500, "Error updating registry %q. %s", in.Address, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, in.Copy())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRegistryList gets the registry list from the database and writes
|
||||||
|
// to the response in json format.
|
||||||
|
func GetRegistryList(c *gin.Context) {
|
||||||
|
repo := session.Repo(c)
|
||||||
|
list, err := store.FromContext(c).RegistryList(repo)
|
||||||
|
if err != nil {
|
||||||
|
c.String(500, "Error getting registry list. %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// copy the registry detail to remove the sensitive
|
||||||
|
// password and token fields.
|
||||||
|
for i, registry := range list {
|
||||||
|
list[i] = registry.Copy()
|
||||||
|
}
|
||||||
|
c.JSON(200, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRegistry deletes the named registry from the database.
|
||||||
|
func DeleteRegistry(c *gin.Context) {
|
||||||
|
var (
|
||||||
|
repo = session.Repo(c)
|
||||||
|
name = c.Param("registry")
|
||||||
|
)
|
||||||
|
registry, err := store.FromContext(c).RegistryFind(repo, name)
|
||||||
|
if err != nil {
|
||||||
|
c.String(404, "Error getting registry %q. %s", name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = store.FromContext(c).RegistryDelete(registry)
|
||||||
|
if err != nil {
|
||||||
|
c.String(500, "Error deleting registry %q. %s", name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.String(204, "")
|
||||||
|
}
|
|
@ -1,56 +0,0 @@
|
||||||
package datastore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
"github.com/russross/meddler"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (db *datastore) GetAgent(id int64) (*model.Agent, error) {
|
|
||||||
var agent = new(model.Agent)
|
|
||||||
var err = meddler.Load(db, agentTable, agent, id)
|
|
||||||
return agent, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *datastore) GetAgentAddr(addr string) (*model.Agent, error) {
|
|
||||||
var agent = new(model.Agent)
|
|
||||||
var err = meddler.QueryRow(db, agent, rebind(agentAddrQuery), addr)
|
|
||||||
return agent, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *datastore) GetAgentList() ([]*model.Agent, error) {
|
|
||||||
var agents = []*model.Agent{}
|
|
||||||
var err = meddler.QueryAll(db, &agents, rebind(agentListQuery))
|
|
||||||
return agents, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *datastore) CreateAgent(agent *model.Agent) error {
|
|
||||||
return meddler.Insert(db, agentTable, agent)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *datastore) UpdateAgent(agent *model.Agent) error {
|
|
||||||
return meddler.Update(db, agentTable, agent)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *datastore) DeleteAgent(agent *model.Agent) error {
|
|
||||||
var _, err = db.Exec(rebind(agentDeleteStmt), agent.ID)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
const agentTable = "agents"
|
|
||||||
|
|
||||||
const agentAddrQuery = `
|
|
||||||
SELECT *
|
|
||||||
FROM agents
|
|
||||||
WHERE agent_addr=?
|
|
||||||
LIMIT 1
|
|
||||||
`
|
|
||||||
|
|
||||||
const agentListQuery = `
|
|
||||||
SELECT *
|
|
||||||
FROM agents
|
|
||||||
ORDER BY agent_addr ASC
|
|
||||||
`
|
|
||||||
|
|
||||||
const agentDeleteStmt = `
|
|
||||||
DELETE FROM agents WHERE agent_id = ?
|
|
||||||
`
|
|
|
@ -1,126 +0,0 @@
|
||||||
package datastore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
"github.com/franela/goblin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAgents(t *testing.T) {
|
|
||||||
db := openTest()
|
|
||||||
defer db.Close()
|
|
||||||
s := From(db)
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Agents", func() {
|
|
||||||
|
|
||||||
// before each test be sure to purge the package
|
|
||||||
// table data from the database.
|
|
||||||
g.BeforeEach(func() {
|
|
||||||
db.Exec("DELETE FROM agents")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should update", func() {
|
|
||||||
agent := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
err1 := s.CreateAgent(&agent)
|
|
||||||
agent.Platform = "windows/amd64"
|
|
||||||
err2 := s.UpdateAgent(&agent)
|
|
||||||
|
|
||||||
getagent, err3 := s.GetAgent(agent.ID)
|
|
||||||
g.Assert(err1 == nil).IsTrue()
|
|
||||||
g.Assert(err2 == nil).IsTrue()
|
|
||||||
g.Assert(err3 == nil).IsTrue()
|
|
||||||
g.Assert(agent.ID).Equal(getagent.ID)
|
|
||||||
g.Assert(agent.Platform).Equal(getagent.Platform)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should create", func() {
|
|
||||||
agent := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
err := s.CreateAgent(&agent)
|
|
||||||
g.Assert(err == nil).IsTrue()
|
|
||||||
g.Assert(agent.ID != 0).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should get by ID", func() {
|
|
||||||
agent := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
|
|
||||||
s.CreateAgent(&agent)
|
|
||||||
getagent, err := s.GetAgent(agent.ID)
|
|
||||||
g.Assert(err == nil).IsTrue()
|
|
||||||
g.Assert(agent.ID).Equal(getagent.ID)
|
|
||||||
g.Assert(agent.Address).Equal(getagent.Address)
|
|
||||||
g.Assert(agent.Platform).Equal(getagent.Platform)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should get by IP address", func() {
|
|
||||||
agent := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
s.CreateAgent(&agent)
|
|
||||||
getagent, err := s.GetAgentAddr(agent.Address)
|
|
||||||
g.Assert(err == nil).IsTrue()
|
|
||||||
g.Assert(agent.ID).Equal(getagent.ID)
|
|
||||||
g.Assert(agent.Address).Equal(getagent.Address)
|
|
||||||
g.Assert(agent.Platform).Equal(getagent.Platform)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should enforce unique IP address", func() {
|
|
||||||
agent1 := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
agent2 := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
err1 := s.CreateAgent(&agent1)
|
|
||||||
err2 := s.CreateAgent(&agent2)
|
|
||||||
g.Assert(err1 == nil).IsTrue()
|
|
||||||
g.Assert(err2 == nil).IsFalse()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should list", func() {
|
|
||||||
agent1 := model.Agent{
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
agent2 := model.Agent{
|
|
||||||
Address: "localhost",
|
|
||||||
Platform: "linux/amd64",
|
|
||||||
}
|
|
||||||
s.CreateAgent(&agent1)
|
|
||||||
s.CreateAgent(&agent2)
|
|
||||||
agents, err := s.GetAgentList()
|
|
||||||
g.Assert(err == nil).IsTrue()
|
|
||||||
g.Assert(len(agents)).Equal(2)
|
|
||||||
g.Assert(agents[0].Address).Equal(agent1.Address)
|
|
||||||
g.Assert(agents[0].Platform).Equal(agent1.Platform)
|
|
||||||
})
|
|
||||||
|
|
||||||
// g.It("Should delete", func() {
|
|
||||||
// user := model.User{
|
|
||||||
// Login: "joe",
|
|
||||||
// Email: "foo@bar.com",
|
|
||||||
// Token: "e42080dddf012c718e476da161d21ad5",
|
|
||||||
// }
|
|
||||||
// s.CreateUser(&user)
|
|
||||||
// _, err1 := s.GetUser(user.ID)
|
|
||||||
// err2 := s.DeleteUser(&user)
|
|
||||||
// _, err3 := s.GetUser(user.ID)
|
|
||||||
// g.Assert(err1 == nil).IsTrue()
|
|
||||||
// g.Assert(err2 == nil).IsTrue()
|
|
||||||
// g.Assert(err3 == nil).IsFalse()
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
package datastore
|
|
||||||
|
|
||||||
//
|
|
||||||
// import (
|
|
||||||
// "github.com/drone/drone/model"
|
|
||||||
// "github.com/russross/meddler"
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// func (db *datastore) GetJob(id int64) (*model.Job, error) {
|
|
||||||
// var job = new(model.Job)
|
|
||||||
// var err = meddler.Load(db, jobTable, job, id)
|
|
||||||
// return job, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (db *datastore) GetJobNumber(build *model.Build, num int) (*model.Job, error) {
|
|
||||||
// var job = new(model.Job)
|
|
||||||
// var err = meddler.QueryRow(db, job, rebind(jobNumberQuery), build.ID, num)
|
|
||||||
// return job, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (db *datastore) GetJobList(build *model.Build) ([]*model.Job, error) {
|
|
||||||
// var jobs = []*model.Job{}
|
|
||||||
// var err = meddler.QueryAll(db, &jobs, rebind(jobListQuery), build.ID)
|
|
||||||
// return jobs, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (db *datastore) CreateJob(job *model.Job) error {
|
|
||||||
// return meddler.Insert(db, jobTable, job)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func (db *datastore) UpdateJob(job *model.Job) error {
|
|
||||||
// return meddler.Update(db, jobTable, job)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const jobTable = "jobs"
|
|
||||||
//
|
|
||||||
// const jobListQuery = `
|
|
||||||
// SELECT *
|
|
||||||
// FROM jobs
|
|
||||||
// WHERE job_build_id = ?
|
|
||||||
// ORDER BY job_number ASC
|
|
||||||
// `
|
|
||||||
//
|
|
||||||
// const jobNumberQuery = `
|
|
||||||
// SELECT *
|
|
||||||
// FROM jobs
|
|
||||||
// WHERE job_build_id = ?
|
|
||||||
// AND job_number = ?
|
|
||||||
// LIMIT 1
|
|
||||||
// `
|
|
|
@ -1,119 +0,0 @@
|
||||||
package datastore
|
|
||||||
|
|
||||||
//
|
|
||||||
// import (
|
|
||||||
// "testing"
|
|
||||||
//
|
|
||||||
// "github.com/drone/drone/model"
|
|
||||||
// "github.com/franela/goblin"
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// func TestJobs(t *testing.T) {
|
|
||||||
// db := openTest()
|
|
||||||
// defer db.Close()
|
|
||||||
//
|
|
||||||
// s := From(db)
|
|
||||||
// g := goblin.Goblin(t)
|
|
||||||
// g.Describe("Job", func() {
|
|
||||||
//
|
|
||||||
// // before each test we purge the package table data from the database.
|
|
||||||
// g.BeforeEach(func() {
|
|
||||||
// db.Exec("DELETE FROM jobs")
|
|
||||||
// db.Exec("DELETE FROM builds")
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// g.It("Should Set a job", func() {
|
|
||||||
// job := &model.Job{
|
|
||||||
// BuildID: 1,
|
|
||||||
// Status: "pending",
|
|
||||||
// ExitCode: 0,
|
|
||||||
// Number: 1,
|
|
||||||
// }
|
|
||||||
// err1 := s.CreateJob(job)
|
|
||||||
// g.Assert(err1 == nil).IsTrue()
|
|
||||||
// g.Assert(job.ID != 0).IsTrue()
|
|
||||||
//
|
|
||||||
// job.Status = "started"
|
|
||||||
// err2 := s.UpdateJob(job)
|
|
||||||
// g.Assert(err2 == nil).IsTrue()
|
|
||||||
//
|
|
||||||
// getjob, err3 := s.GetJob(job.ID)
|
|
||||||
// g.Assert(err3 == nil).IsTrue()
|
|
||||||
// g.Assert(getjob.Status).Equal(job.Status)
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// g.It("Should Get a Job by ID", func() {
|
|
||||||
// job := &model.Job{
|
|
||||||
// BuildID: 1,
|
|
||||||
// Status: "pending",
|
|
||||||
// ExitCode: 1,
|
|
||||||
// Number: 1,
|
|
||||||
// Environment: map[string]string{"foo": "bar"},
|
|
||||||
// }
|
|
||||||
// err1 := s.CreateJob(job)
|
|
||||||
// g.Assert(err1 == nil).IsTrue()
|
|
||||||
// g.Assert(job.ID != 0).IsTrue()
|
|
||||||
//
|
|
||||||
// getjob, err2 := s.GetJob(job.ID)
|
|
||||||
// g.Assert(err2 == nil).IsTrue()
|
|
||||||
// g.Assert(getjob.ID).Equal(job.ID)
|
|
||||||
// g.Assert(getjob.Status).Equal(job.Status)
|
|
||||||
// g.Assert(getjob.ExitCode).Equal(job.ExitCode)
|
|
||||||
// g.Assert(getjob.Environment).Equal(job.Environment)
|
|
||||||
// g.Assert(getjob.Environment["foo"]).Equal("bar")
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// g.It("Should Get a Job by Number", func() {
|
|
||||||
// job := &model.Job{
|
|
||||||
// BuildID: 1,
|
|
||||||
// Status: "pending",
|
|
||||||
// ExitCode: 1,
|
|
||||||
// Number: 1,
|
|
||||||
// }
|
|
||||||
// err1 := s.CreateJob(job)
|
|
||||||
// g.Assert(err1 == nil).IsTrue()
|
|
||||||
// g.Assert(job.ID != 0).IsTrue()
|
|
||||||
//
|
|
||||||
// getjob, err2 := s.GetJobNumber(&model.Build{ID: 1}, 1)
|
|
||||||
// g.Assert(err2 == nil).IsTrue()
|
|
||||||
// g.Assert(getjob.ID).Equal(job.ID)
|
|
||||||
// g.Assert(getjob.Status).Equal(job.Status)
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// g.It("Should Get a List of Jobs by Commit", func() {
|
|
||||||
//
|
|
||||||
// build := model.Build{
|
|
||||||
// RepoID: 1,
|
|
||||||
// Status: model.StatusSuccess,
|
|
||||||
// }
|
|
||||||
// jobs := []*model.Job{
|
|
||||||
// {
|
|
||||||
// BuildID: 1,
|
|
||||||
// Status: "success",
|
|
||||||
// ExitCode: 0,
|
|
||||||
// Number: 1,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// BuildID: 3,
|
|
||||||
// Status: "error",
|
|
||||||
// ExitCode: 1,
|
|
||||||
// Number: 2,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// BuildID: 5,
|
|
||||||
// Status: "pending",
|
|
||||||
// ExitCode: 0,
|
|
||||||
// Number: 3,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// err1 := s.CreateBuild(&build, jobs...)
|
|
||||||
// g.Assert(err1 == nil).IsTrue()
|
|
||||||
// getjobs, err2 := s.GetJobList(&build)
|
|
||||||
// g.Assert(err2 == nil).IsTrue()
|
|
||||||
// g.Assert(len(getjobs)).Equal(3)
|
|
||||||
// g.Assert(getjobs[0].Number).Equal(1)
|
|
||||||
// g.Assert(getjobs[0].Status).Equal(model.StatusSuccess)
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
35
store/datastore/registry.go
Normal file
35
store/datastore/registry.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package datastore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/drone/drone/store/datastore/sql"
|
||||||
|
"github.com/russross/meddler"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *datastore) RegistryFind(repo *model.Repo, addr string) (*model.Registry, error) {
|
||||||
|
stmt := sql.Lookup(db.driver, "registry-find-repo-addr")
|
||||||
|
data := new(model.Registry)
|
||||||
|
err := meddler.QueryRow(db, data, stmt, repo.ID, addr)
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) RegistryList(repo *model.Repo) ([]*model.Registry, error) {
|
||||||
|
stmt := sql.Lookup(db.driver, "registry-find-repo")
|
||||||
|
data := []*model.Registry{}
|
||||||
|
err := meddler.QueryAll(db, &data, stmt, repo.ID)
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) RegistryCreate(registry *model.Registry) error {
|
||||||
|
return meddler.Insert(db, "registry", registry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) RegistryUpdate(registry *model.Registry) error {
|
||||||
|
return meddler.Update(db, "registry", registry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) RegistryDelete(registry *model.Registry) error {
|
||||||
|
stmt := sql.Lookup(db.driver, "registry-delete")
|
||||||
|
_, err := db.Exec(stmt, registry.ID)
|
||||||
|
return err
|
||||||
|
}
|
142
store/datastore/registry_test.go
Normal file
142
store/datastore/registry_test.go
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
package datastore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRegistryFind(t *testing.T) {
|
||||||
|
s := newTest()
|
||||||
|
defer func() {
|
||||||
|
s.Exec("delete from registry")
|
||||||
|
s.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
err := s.RegistryCreate(&model.Registry{
|
||||||
|
RepoID: 1,
|
||||||
|
Address: "index.docker.io",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "bar",
|
||||||
|
Email: "foo@bar.com",
|
||||||
|
Token: "12345",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error: insert registry: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registry, err := s.RegistryFind(&model.Repo{ID: 1}, "index.docker.io")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got, want := registry.RepoID, int64(1); got != want {
|
||||||
|
t.Errorf("Want repo id %d, got %d", want, got)
|
||||||
|
}
|
||||||
|
if got, want := registry.Address, "index.docker.io"; got != want {
|
||||||
|
t.Errorf("Want registry address %s, got %s", want, got)
|
||||||
|
}
|
||||||
|
if got, want := registry.Username, "foo"; got != want {
|
||||||
|
t.Errorf("Want registry username %s, got %s", want, got)
|
||||||
|
}
|
||||||
|
if got, want := registry.Password, "bar"; got != want {
|
||||||
|
t.Errorf("Want registry password %s, got %s", want, got)
|
||||||
|
}
|
||||||
|
if got, want := registry.Email, "foo@bar.com"; got != want {
|
||||||
|
t.Errorf("Want registry email %s, got %s", want, got)
|
||||||
|
}
|
||||||
|
if got, want := registry.Token, "12345"; got != want {
|
||||||
|
t.Errorf("Want registry token %s, got %s", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegistryList(t *testing.T) {
|
||||||
|
s := newTest()
|
||||||
|
defer func() {
|
||||||
|
s.Exec("delete from registry")
|
||||||
|
s.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
s.RegistryCreate(&model.Registry{
|
||||||
|
RepoID: 1,
|
||||||
|
Address: "index.docker.io",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "bar",
|
||||||
|
})
|
||||||
|
s.RegistryCreate(&model.Registry{
|
||||||
|
RepoID: 1,
|
||||||
|
Address: "foo.docker.io",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "bar",
|
||||||
|
})
|
||||||
|
|
||||||
|
list, err := s.RegistryList(&model.Repo{ID: 1})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got, want := len(list), 2; got != want {
|
||||||
|
t.Errorf("Want %d registries, got %d", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegistryUpdate(t *testing.T) {
|
||||||
|
s := newTest()
|
||||||
|
defer func() {
|
||||||
|
s.Exec("delete from registry")
|
||||||
|
s.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
registry := &model.Registry{
|
||||||
|
RepoID: 1,
|
||||||
|
Address: "index.docker.io",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "bar",
|
||||||
|
}
|
||||||
|
if err := s.RegistryCreate(registry); err != nil {
|
||||||
|
t.Errorf("Unexpected error: insert registry: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
registry.Password = "qux"
|
||||||
|
if err := s.RegistryUpdate(registry); err != nil {
|
||||||
|
t.Errorf("Unexpected error: update registry: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updated, err := s.RegistryFind(&model.Repo{ID: 1}, "index.docker.io")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got, want := updated.Password, "qux"; got != want {
|
||||||
|
t.Errorf("Want registry password %s, got %s", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegistryIndexes(t *testing.T) {
|
||||||
|
s := newTest()
|
||||||
|
defer func() {
|
||||||
|
s.Exec("delete from registry")
|
||||||
|
s.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := s.RegistryCreate(&model.Registry{
|
||||||
|
RepoID: 1,
|
||||||
|
Address: "index.docker.io",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "bar",
|
||||||
|
}); err != nil {
|
||||||
|
t.Errorf("Unexpected error: insert registry: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail due to duplicate addr
|
||||||
|
if err := s.RegistryCreate(&model.Registry{
|
||||||
|
RepoID: 1,
|
||||||
|
Address: "index.docker.io",
|
||||||
|
Username: "baz",
|
||||||
|
Password: "qux",
|
||||||
|
}); err == nil {
|
||||||
|
t.Errorf("Unexpected error: dupliate address")
|
||||||
|
}
|
||||||
|
}
|
34
store/datastore/sql/postgres/files/registry.sql
Normal file
34
store/datastore/sql/postgres/files/registry.sql
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-- name: registry-find-repo
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = $1
|
||||||
|
|
||||||
|
-- name: registry-find-repo-addr
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = $1
|
||||||
|
AND registry_addr = $2
|
||||||
|
|
||||||
|
-- name: registry-delete-repo
|
||||||
|
|
||||||
|
DELETE FROM registry WHERE registry_repo_id = $1
|
||||||
|
|
||||||
|
-- name: registry-delete
|
||||||
|
|
||||||
|
DELETE FROM registry WHERE registry_id = $1
|
|
@ -15,6 +15,10 @@ var index = map[string]string{
|
||||||
"procs-find-build-pid": procsFindBuildPid,
|
"procs-find-build-pid": procsFindBuildPid,
|
||||||
"procs-find-build-ppid": procsFindBuildPpid,
|
"procs-find-build-ppid": procsFindBuildPpid,
|
||||||
"procs-delete-build": procsDeleteBuild,
|
"procs-delete-build": procsDeleteBuild,
|
||||||
|
"registry-find-repo": registryFindRepo,
|
||||||
|
"registry-find-repo-addr": registryFindRepoAddr,
|
||||||
|
"registry-delete-repo": registryDeleteRepo,
|
||||||
|
"registry-delete": registryDelete,
|
||||||
}
|
}
|
||||||
|
|
||||||
var filesFindBuild = `
|
var filesFindBuild = `
|
||||||
|
@ -149,3 +153,38 @@ WHERE proc_build_id = $1
|
||||||
var procsDeleteBuild = `
|
var procsDeleteBuild = `
|
||||||
DELETE FROM procs WHERE proc_build_id = $1
|
DELETE FROM procs WHERE proc_build_id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var registryFindRepo = `
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
var registryFindRepoAddr = `
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = $1
|
||||||
|
AND registry_addr = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
var registryDeleteRepo = `
|
||||||
|
DELETE FROM registry WHERE registry_repo_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
var registryDelete = `
|
||||||
|
DELETE FROM registry WHERE registry_id = $1
|
||||||
|
`
|
||||||
|
|
34
store/datastore/sql/sqlite/files/registry.sql
Normal file
34
store/datastore/sql/sqlite/files/registry.sql
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-- name: registry-find-repo
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = ?
|
||||||
|
|
||||||
|
-- name: registry-find-repo-addr
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = ?
|
||||||
|
AND registry_addr = ?
|
||||||
|
|
||||||
|
-- name: registry-delete-repo
|
||||||
|
|
||||||
|
DELETE FROM registry WHERE registry_repo_id = ?
|
||||||
|
|
||||||
|
-- name: registry-delete
|
||||||
|
|
||||||
|
DELETE FROM registry WHERE registry_id = ?
|
|
@ -15,6 +15,10 @@ var index = map[string]string{
|
||||||
"procs-find-build-pid": procsFindBuildPid,
|
"procs-find-build-pid": procsFindBuildPid,
|
||||||
"procs-find-build-ppid": procsFindBuildPpid,
|
"procs-find-build-ppid": procsFindBuildPpid,
|
||||||
"procs-delete-build": procsDeleteBuild,
|
"procs-delete-build": procsDeleteBuild,
|
||||||
|
"registry-find-repo": registryFindRepo,
|
||||||
|
"registry-find-repo-addr": registryFindRepoAddr,
|
||||||
|
"registry-delete-repo": registryDeleteRepo,
|
||||||
|
"registry-delete": registryDelete,
|
||||||
}
|
}
|
||||||
|
|
||||||
var filesFindBuild = `
|
var filesFindBuild = `
|
||||||
|
@ -149,3 +153,38 @@ WHERE proc_build_id = ?
|
||||||
var procsDeleteBuild = `
|
var procsDeleteBuild = `
|
||||||
DELETE FROM procs WHERE proc_build_id = ?
|
DELETE FROM procs WHERE proc_build_id = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var registryFindRepo = `
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
var registryFindRepoAddr = `
|
||||||
|
SELECT
|
||||||
|
registry_id
|
||||||
|
,registry_repo_id
|
||||||
|
,registry_addr
|
||||||
|
,registry_username
|
||||||
|
,registry_password
|
||||||
|
,registry_email
|
||||||
|
,registry_token
|
||||||
|
FROM registry
|
||||||
|
WHERE registry_repo_id = ?
|
||||||
|
AND registry_addr = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
var registryDeleteRepo = `
|
||||||
|
DELETE FROM registry WHERE registry_repo_id = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
var registryDelete = `
|
||||||
|
DELETE FROM registry WHERE registry_id = ?
|
||||||
|
`
|
||||||
|
|
|
@ -133,17 +133,23 @@ type Store interface {
|
||||||
// // WriteLog writes the job logs to the datastore.
|
// // WriteLog writes the job logs to the datastore.
|
||||||
// WriteLog(*model.Job, io.Reader) error
|
// WriteLog(*model.Job, io.Reader) error
|
||||||
|
|
||||||
GetAgent(int64) (*model.Agent, error)
|
// GetAgent(int64) (*model.Agent, error)
|
||||||
|
//
|
||||||
|
// GetAgentAddr(string) (*model.Agent, error)
|
||||||
|
//
|
||||||
|
// GetAgentList() ([]*model.Agent, error)
|
||||||
|
//
|
||||||
|
// CreateAgent(*model.Agent) error
|
||||||
|
//
|
||||||
|
// UpdateAgent(*model.Agent) error
|
||||||
|
//
|
||||||
|
// DeleteAgent(*model.Agent) error
|
||||||
|
|
||||||
GetAgentAddr(string) (*model.Agent, error)
|
RegistryFind(*model.Repo, string) (*model.Registry, error)
|
||||||
|
RegistryList(*model.Repo) ([]*model.Registry, error)
|
||||||
GetAgentList() ([]*model.Agent, error)
|
RegistryCreate(*model.Registry) error
|
||||||
|
RegistryUpdate(*model.Registry) error
|
||||||
CreateAgent(*model.Agent) error
|
RegistryDelete(*model.Registry) error
|
||||||
|
|
||||||
UpdateAgent(*model.Agent) error
|
|
||||||
|
|
||||||
DeleteAgent(*model.Agent) error
|
|
||||||
|
|
||||||
ProcLoad(int64) (*model.Proc, error)
|
ProcLoad(int64) (*model.Proc, error)
|
||||||
ProcFind(*model.Build, int) (*model.Proc, error)
|
ProcFind(*model.Build, int) (*model.Proc, error)
|
||||||
|
@ -388,26 +394,26 @@ func UpdateBuild(c context.Context, build *model.Build) error {
|
||||||
// return FromContext(c).WriteLog(job, r)
|
// return FromContext(c).WriteLog(job, r)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func GetAgent(c context.Context, id int64) (*model.Agent, error) {
|
// func GetAgent(c context.Context, id int64) (*model.Agent, error) {
|
||||||
return FromContext(c).GetAgent(id)
|
// return FromContext(c).GetAgent(id)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func GetAgentAddr(c context.Context, addr string) (*model.Agent, error) {
|
// func GetAgentAddr(c context.Context, addr string) (*model.Agent, error) {
|
||||||
return FromContext(c).GetAgentAddr(addr)
|
// return FromContext(c).GetAgentAddr(addr)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func GetAgentList(c context.Context) ([]*model.Agent, error) {
|
// func GetAgentList(c context.Context) ([]*model.Agent, error) {
|
||||||
return FromContext(c).GetAgentList()
|
// return FromContext(c).GetAgentList()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func CreateAgent(c context.Context, agent *model.Agent) error {
|
// func CreateAgent(c context.Context, agent *model.Agent) error {
|
||||||
return FromContext(c).CreateAgent(agent)
|
// return FromContext(c).CreateAgent(agent)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func UpdateAgent(c context.Context, agent *model.Agent) error {
|
// func UpdateAgent(c context.Context, agent *model.Agent) error {
|
||||||
return FromContext(c).UpdateAgent(agent)
|
// return FromContext(c).UpdateAgent(agent)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func DeleteAgent(c context.Context, agent *model.Agent) error {
|
// func DeleteAgent(c context.Context, agent *model.Agent) error {
|
||||||
return FromContext(c).DeleteAgent(agent)
|
// return FromContext(c).DeleteAgent(agent)
|
||||||
}
|
// }
|
||||||
|
|
Loading…
Reference in a new issue