Integrated store layer for org secrets

This commit is contained in:
Thomas Boerger 2016-07-31 22:40:21 +02:00
parent 0e424a2527
commit 889b88d38f
No known key found for this signature in database
GPG key ID: 5A388F55283960B6
7 changed files with 371 additions and 110 deletions

View file

@ -0,0 +1,53 @@
package datastore
import (
"github.com/drone/drone/model"
"github.com/russross/meddler"
)
func (db *datastore) GetSecretList(repo *model.Repo) ([]*model.RepoSecret, error) {
var secrets = []*model.RepoSecret{}
var err = meddler.QueryAll(db, &secrets, rebind(secretListQuery), repo.ID)
return secrets, err
}
func (db *datastore) GetSecret(repo *model.Repo, name string) (*model.RepoSecret, error) {
var secret = new(model.RepoSecret)
var err = meddler.QueryRow(db, secret, rebind(secretNameQuery), repo.ID, name)
return secret, err
}
func (db *datastore) SetSecret(sec *model.RepoSecret) error {
var got = new(model.RepoSecret)
var err = meddler.QueryRow(db, got, rebind(secretNameQuery), sec.RepoID, sec.Name)
if err == nil && got.ID != 0 {
sec.ID = got.ID // update existing id
}
return meddler.Save(db, secretTable, sec)
}
func (db *datastore) DeleteSecret(sec *model.RepoSecret) error {
_, err := db.Exec(rebind(secretDeleteStmt), sec.ID)
return err
}
const secretTable = "secrets"
const secretListQuery = `
SELECT *
FROM secrets
WHERE secret_repo_id = ?
`
const secretNameQuery = `
SELECT *
FROM secrets
WHERE secret_repo_id = ?
AND secret_name = ?
LIMIT 1;
`
const secretDeleteStmt = `
DELETE FROM secrets
WHERE secret_id = ?
`

View file

@ -0,0 +1,94 @@
package datastore
import (
"testing"
"github.com/drone/drone/model"
"github.com/franela/goblin"
)
func TestRepoSecrets(t *testing.T) {
db := openTest()
defer db.Close()
s := From(db)
g := goblin.Goblin(t)
g.Describe("RepoSecrets", func() {
// before each test be sure to purge the package
// table data from the database.
g.BeforeEach(func() {
db.Exec(rebind("DELETE FROM secrets"))
})
g.It("Should set and get a secret", func() {
secret := &model.RepoSecret{
RepoID: 1,
Name: "foo",
Value: "bar",
Images: []string{"docker", "gcr"},
Events: []string{"push", "tag"},
}
err := s.SetSecret(secret)
g.Assert(err == nil).IsTrue()
g.Assert(secret.ID != 0).IsTrue()
got, err := s.GetSecret(&model.Repo{ID: 1}, secret.Name)
g.Assert(err == nil).IsTrue()
g.Assert(got.Name).Equal(secret.Name)
g.Assert(got.Value).Equal(secret.Value)
g.Assert(got.Images).Equal(secret.Images)
g.Assert(got.Events).Equal(secret.Events)
})
g.It("Should update a secret", func() {
secret := &model.RepoSecret{
RepoID: 1,
Name: "foo",
Value: "bar",
}
s.SetSecret(secret)
secret.Value = "baz"
s.SetSecret(secret)
got, err := s.GetSecret(&model.Repo{ID: 1}, secret.Name)
g.Assert(err == nil).IsTrue()
g.Assert(got.Name).Equal(secret.Name)
g.Assert(got.Value).Equal(secret.Value)
})
g.It("Should list secrets", func() {
s.SetSecret(&model.RepoSecret{
RepoID: 1,
Name: "foo",
Value: "bar",
})
s.SetSecret(&model.RepoSecret{
RepoID: 1,
Name: "bar",
Value: "baz",
})
secrets, err := s.GetSecretList(&model.Repo{ID: 1})
g.Assert(err == nil).IsTrue()
g.Assert(len(secrets)).Equal(2)
})
g.It("Should delete a secret", func() {
secret := &model.RepoSecret{
RepoID: 1,
Name: "foo",
Value: "bar",
}
s.SetSecret(secret)
_, err := s.GetSecret(&model.Repo{ID: 1}, secret.Name)
g.Assert(err == nil).IsTrue()
err = s.DeleteSecret(secret)
g.Assert(err == nil).IsTrue()
_, err = s.GetSecret(&model.Repo{ID: 1}, secret.Name)
g.Assert(err != nil).IsTrue("expect a no rows in result set error")
})
})
}

View file

@ -2,52 +2,32 @@ package datastore
import ( import (
"github.com/drone/drone/model" "github.com/drone/drone/model"
"github.com/russross/meddler"
) )
func (db *datastore) GetSecretList(repo *model.Repo) ([]*model.Secret, error) { func (db *datastore) GetMergedSecretList(repo *model.Repo) ([]*model.Secret, error) {
var secrets = []*model.Secret{} var (
var err = meddler.QueryAll(db, &secrets, rebind(secretListQuery), repo.ID) secrets []*model.Secret
return secrets, err )
repoSecs, err := db.GetSecretList(repo)
if err != nil {
return nil, err
} }
func (db *datastore) GetSecret(repo *model.Repo, name string) (*model.Secret, error) { for _, secret := range repoSecs {
var secret = new(model.Secret) secrets = append(secrets, secret.Secret())
var err = meddler.QueryRow(db, secret, rebind(secretNameQuery), repo.ID, name)
return secret, err
} }
func (db *datastore) SetSecret(sec *model.Secret) error { teamSecs, err := db.GetTeamSecretList(repo.Owner)
var got = new(model.Secret)
var err = meddler.QueryRow(db, got, rebind(secretNameQuery), sec.RepoID, sec.Name) if err != nil {
if err == nil && got.ID != 0 { return nil, err
sec.ID = got.ID // update existing id
}
return meddler.Save(db, secretTable, sec)
} }
func (db *datastore) DeleteSecret(sec *model.Secret) error { for _, secret := range teamSecs {
_, err := db.Exec(rebind(secretDeleteStmt), sec.ID) secrets = append(secrets, secret.Secret())
return err
} }
const secretTable = "secrets" return secrets, nil
}
const secretListQuery = `
SELECT *
FROM secrets
WHERE secret_repo_id = ?
`
const secretNameQuery = `
SELECT *
FROM secrets
WHERE secret_repo_id = ?
AND secret_name = ?
LIMIT 1;
`
const secretDeleteStmt = `
DELETE FROM secrets
WHERE secret_id = ?
`

View file

@ -19,76 +19,28 @@ func TestSecrets(t *testing.T) {
// table data from the database. // table data from the database.
g.BeforeEach(func() { g.BeforeEach(func() {
db.Exec(rebind("DELETE FROM secrets")) db.Exec(rebind("DELETE FROM secrets"))
db.Exec(rebind("DELETE FROM team_secrets"))
}) })
g.It("Should set and get a secret", func() { g.It("Should list all secrets", func() {
secret := &model.Secret{ teamSec := &model.TeamSecret{
RepoID: 1, Key: "octocat",
Name: "foo", Name: "foo",
Value: "bar", Value: "team",
Images: []string{"docker", "gcr"},
Events: []string{"push", "tag"},
} }
err := s.SetSecret(secret)
g.Assert(err == nil).IsTrue()
g.Assert(secret.ID != 0).IsTrue()
got, err := s.GetSecret(&model.Repo{ID: 1}, secret.Name) repoSec := &model.RepoSecret{
g.Assert(err == nil).IsTrue()
g.Assert(got.Name).Equal(secret.Name)
g.Assert(got.Value).Equal(secret.Value)
g.Assert(got.Images).Equal(secret.Images)
g.Assert(got.Events).Equal(secret.Events)
})
g.It("Should update a secret", func() {
secret := &model.Secret{
RepoID: 1, RepoID: 1,
Name: "foo", Name: "foo",
Value: "bar", Value: "repo",
} }
s.SetSecret(secret)
secret.Value = "baz"
s.SetSecret(secret)
got, err := s.GetSecret(&model.Repo{ID: 1}, secret.Name) s.SetSecret(repoSec)
g.Assert(err == nil).IsTrue() s.SetTeamSecret(teamSec)
g.Assert(got.Name).Equal(secret.Name)
g.Assert(got.Value).Equal(secret.Value)
})
g.It("Should list secrets", func() { secrets, err := s.GetMergedSecretList(&model.Repo{ID: 1, Owner: "octocat"})
s.SetSecret(&model.Secret{
RepoID: 1,
Name: "foo",
Value: "bar",
})
s.SetSecret(&model.Secret{
RepoID: 1,
Name: "bar",
Value: "baz",
})
secrets, err := s.GetSecretList(&model.Repo{ID: 1})
g.Assert(err == nil).IsTrue() g.Assert(err == nil).IsTrue()
g.Assert(len(secrets)).Equal(2) g.Assert(len(secrets)).Equal(2)
}) })
g.It("Should delete a secret", func() {
secret := &model.Secret{
RepoID: 1,
Name: "foo",
Value: "bar",
}
s.SetSecret(secret)
_, err := s.GetSecret(&model.Repo{ID: 1}, secret.Name)
g.Assert(err == nil).IsTrue()
err = s.DeleteSecret(secret)
g.Assert(err == nil).IsTrue()
_, err = s.GetSecret(&model.Repo{ID: 1}, secret.Name)
g.Assert(err != nil).IsTrue("expect a no rows in result set error")
})
}) })
} }

View file

@ -0,0 +1,53 @@
package datastore
import (
"github.com/drone/drone/model"
"github.com/russross/meddler"
)
func (db *datastore) GetTeamSecretList(team string) ([]*model.TeamSecret, error) {
var secrets = []*model.TeamSecret{}
var err = meddler.QueryAll(db, &secrets, rebind(teamSecretListQuery), team)
return secrets, err
}
func (db *datastore) GetTeamSecret(team, name string) (*model.TeamSecret, error) {
var secret = new(model.TeamSecret)
var err = meddler.QueryRow(db, secret, rebind(teamSecretNameQuery), team, name)
return secret, err
}
func (db *datastore) SetTeamSecret(sec *model.TeamSecret) error {
var got = new(model.TeamSecret)
var err = meddler.QueryRow(db, got, rebind(teamSecretNameQuery), sec.Key, sec.Name)
if err == nil && got.ID != 0 {
sec.ID = got.ID // update existing id
}
return meddler.Save(db, teamSecretTable, sec)
}
func (db *datastore) DeleteTeamSecret(sec *model.TeamSecret) error {
_, err := db.Exec(rebind(teamSecretDeleteStmt), sec.ID)
return err
}
const teamSecretTable = "team_secrets"
const teamSecretListQuery = `
SELECT *
FROM team_secrets
WHERE team_secret_key = ?
`
const teamSecretNameQuery = `
SELECT *
FROM team_secrets
WHERE team_secret_key = ?
AND team_secret_name = ?
LIMIT 1;
`
const teamSecretDeleteStmt = `
DELETE FROM team_secrets
WHERE team_secret_id = ?
`

View file

@ -0,0 +1,94 @@
package datastore
import (
"testing"
"github.com/drone/drone/model"
"github.com/franela/goblin"
)
func TestTeamSecrets(t *testing.T) {
db := openTest()
defer db.Close()
s := From(db)
g := goblin.Goblin(t)
g.Describe("TeamSecrets", func() {
// before each test be sure to purge the package
// table data from the database.
g.BeforeEach(func() {
db.Exec(rebind("DELETE FROM team_secrets"))
})
g.It("Should set and get a secret", func() {
secret := &model.TeamSecret{
Key: "octocat",
Name: "foo",
Value: "bar",
Images: []string{"docker", "gcr"},
Events: []string{"push", "tag"},
}
err := s.SetTeamSecret(secret)
g.Assert(err == nil).IsTrue()
g.Assert(secret.ID != 0).IsTrue()
got, err := s.GetTeamSecret("octocat", secret.Name)
g.Assert(err == nil).IsTrue()
g.Assert(got.Name).Equal(secret.Name)
g.Assert(got.Value).Equal(secret.Value)
g.Assert(got.Images).Equal(secret.Images)
g.Assert(got.Events).Equal(secret.Events)
})
g.It("Should update a secret", func() {
secret := &model.TeamSecret{
Key: "octocat",
Name: "foo",
Value: "bar",
}
s.SetTeamSecret(secret)
secret.Value = "baz"
s.SetTeamSecret(secret)
got, err := s.GetTeamSecret("octocat", secret.Name)
g.Assert(err == nil).IsTrue()
g.Assert(got.Name).Equal(secret.Name)
g.Assert(got.Value).Equal(secret.Value)
})
g.It("Should list secrets", func() {
s.SetTeamSecret(&model.TeamSecret{
Key: "octocat",
Name: "foo",
Value: "bar",
})
s.SetTeamSecret(&model.TeamSecret{
Key: "octocat",
Name: "bar",
Value: "baz",
})
secrets, err := s.GetTeamSecretList("octocat")
g.Assert(err == nil).IsTrue()
g.Assert(len(secrets)).Equal(2)
})
g.It("Should delete a secret", func() {
secret := &model.TeamSecret{
Key: "octocat",
Name: "foo",
Value: "bar",
}
s.SetTeamSecret(secret)
_, err := s.GetTeamSecret("octocat", secret.Name)
g.Assert(err == nil).IsTrue()
err = s.DeleteTeamSecret(secret)
g.Assert(err == nil).IsTrue()
_, err = s.GetTeamSecret("octocat", secret.Name)
g.Assert(err != nil).IsTrue("expect a no rows in result set error")
})
})
}

View file

@ -59,16 +59,31 @@ type Store interface {
DeleteRepo(*model.Repo) error DeleteRepo(*model.Repo) error
// GetSecretList gets a list of repository secrets // GetSecretList gets a list of repository secrets
GetSecretList(*model.Repo) ([]*model.Secret, error) GetSecretList(*model.Repo) ([]*model.RepoSecret, error)
// GetSecret gets the named repository secret. // GetSecret gets the named repository secret.
GetSecret(*model.Repo, string) (*model.Secret, error) GetSecret(*model.Repo, string) (*model.RepoSecret, error)
// SetSecret sets the named repository secret. // SetSecret sets the named repository secret.
SetSecret(*model.Secret) error SetSecret(*model.RepoSecret) error
// DeleteSecret deletes the named repository secret. // DeleteSecret deletes the named repository secret.
DeleteSecret(*model.Secret) error DeleteSecret(*model.RepoSecret) error
// GetTeamSecretList gets a list of team secrets
GetTeamSecretList(string) ([]*model.TeamSecret, error)
// GetTeamSecret gets the named team secret.
GetTeamSecret(string, string) (*model.TeamSecret, error)
// SetTeamSecret sets the named team secret.
SetTeamSecret(*model.TeamSecret) error
// DeleteTeamSecret deletes the named team secret.
DeleteTeamSecret(*model.TeamSecret) error
// GetMergedSecretList gets a list of repo and team secrets
GetMergedSecretList(*model.Repo) ([]*model.Secret, error)
// GetBuild gets a build by unique ID. // GetBuild gets a build by unique ID.
GetBuild(int64) (*model.Build, error) GetBuild(int64) (*model.Build, error)
@ -202,22 +217,42 @@ func DeleteRepo(c context.Context, repo *model.Repo) error {
return FromContext(c).DeleteRepo(repo) return FromContext(c).DeleteRepo(repo)
} }
func GetSecretList(c context.Context, r *model.Repo) ([]*model.Secret, error) { func GetSecretList(c context.Context, r *model.Repo) ([]*model.RepoSecret, error) {
return FromContext(c).GetSecretList(r) return FromContext(c).GetSecretList(r)
} }
func GetSecret(c context.Context, r *model.Repo, name string) (*model.Secret, error) { func GetSecret(c context.Context, r *model.Repo, name string) (*model.RepoSecret, error) {
return FromContext(c).GetSecret(r, name) return FromContext(c).GetSecret(r, name)
} }
func SetSecret(c context.Context, s *model.Secret) error { func SetSecret(c context.Context, s *model.RepoSecret) error {
return FromContext(c).SetSecret(s) return FromContext(c).SetSecret(s)
} }
func DeleteSecret(c context.Context, s *model.Secret) error { func DeleteSecret(c context.Context, s *model.RepoSecret) error {
return FromContext(c).DeleteSecret(s) return FromContext(c).DeleteSecret(s)
} }
func GetTeamSecretList(c context.Context, team string) ([]*model.TeamSecret, error) {
return FromContext(c).GetTeamSecretList(team)
}
func GetTeamSecret(c context.Context, team, name string) (*model.TeamSecret, error) {
return FromContext(c).GetTeamSecret(team, name)
}
func SetTeamSecret(c context.Context, s *model.TeamSecret) error {
return FromContext(c).SetTeamSecret(s)
}
func DeleteTeamSecret(c context.Context, s *model.TeamSecret) error {
return FromContext(c).DeleteTeamSecret(s)
}
func GetMergedSecretList(c context.Context, r *model.Repo) ([]*model.Secret, error) {
return FromContext(c).GetMergedSecretList(r)
}
func GetBuild(c context.Context, id int64) (*model.Build, error) { func GetBuild(c context.Context, id int64) (*model.Build, error) {
return FromContext(c).GetBuild(id) return FromContext(c).GetBuild(id)
} }