mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-22 09:51:01 +00:00
Add global registry from docker config file on woodpecker server
This commit is contained in:
parent
581f08b54b
commit
de010dfb39
11 changed files with 188 additions and 9 deletions
|
@ -133,6 +133,10 @@ var flags = []cli.Flag{
|
|||
EnvVar: "DRONE_VOLUME",
|
||||
Name: "volume",
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "DRONE_DOCKER_CONFIG",
|
||||
Name: "docker-config",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
EnvVar: "DRONE_ENVIRONMENT",
|
||||
Name: "environment",
|
||||
|
|
|
@ -60,7 +60,14 @@ func setupSecretService(c *cli.Context, s store.Store) model.SecretService {
|
|||
}
|
||||
|
||||
func setupRegistryService(c *cli.Context, s store.Store) model.RegistryService {
|
||||
return registry.New(s)
|
||||
if c.String("docker-config") != "" {
|
||||
return registry.Combined(
|
||||
registry.New(s),
|
||||
registry.Filesystem(c.String("docker-config")),
|
||||
)
|
||||
} else {
|
||||
return registry.New(s)
|
||||
}
|
||||
}
|
||||
|
||||
func setupEnvironService(c *cli.Context, s store.Store) model.EnvironService {
|
||||
|
|
4
go.mod
4
go.mod
|
@ -10,8 +10,10 @@ require (
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/dgrijalva/jwt-go v0.0.0-20150904212456-c1da56349675
|
||||
github.com/dimfeld/httptreemux v5.0.1+incompatible
|
||||
github.com/docker/cli v0.0.0-20200303215952-eb310fca4956
|
||||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible
|
||||
github.com/docker/docker v1.13.1
|
||||
github.com/docker/docker-credential-helpers v0.6.3 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/docker/libcompose v0.4.0
|
||||
|
|
7
go.sum
7
go.sum
|
@ -36,10 +36,17 @@ github.com/dgrijalva/jwt-go v0.0.0-20150904212456-c1da56349675 h1:MIkcjohFTgoQVD
|
|||
github.com/dgrijalva/jwt-go v0.0.0-20150904212456-c1da56349675/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA=
|
||||
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
|
||||
github.com/docker/cli v0.0.0-20200303215952-eb310fca4956 h1:5/ZRsUbguX7xFNLlbxVQY/yhD3Psy+vylKZrNme5BJs=
|
||||
github.com/docker/cli v0.0.0-20200303215952-eb310fca4956/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v17.12.1-ce-rc2+incompatible h1:ESUycEAqvFuLglAHkUW66rCc2djYtd3i1x231svLq9o=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
|
||||
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible h1:G2hY8RD7jB9QaSmcb8mYEIg8QbEvVAB7se8+lXHZHfg=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
|
|
|
@ -31,6 +31,12 @@ type RegistryService interface {
|
|||
RegistryDelete(*Repo, string) error
|
||||
}
|
||||
|
||||
// RegistryService defines a service for managing registries.
|
||||
type ReadOnlyRegistryService interface {
|
||||
RegistryFind(*Repo, string) (*Registry, error)
|
||||
RegistryList(*Repo) ([]*Registry, error)
|
||||
}
|
||||
|
||||
// RegistryStore persists registry information to storage.
|
||||
type RegistryStore interface {
|
||||
RegistryFind(*Repo, string) (*Registry, error)
|
||||
|
|
55
plugins/registry/combine.go
Normal file
55
plugins/registry/combine.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"github.com/laszlocph/woodpecker/model"
|
||||
)
|
||||
|
||||
type combined struct {
|
||||
registries []model.ReadOnlyRegistryService
|
||||
dbRegistry model.RegistryService
|
||||
}
|
||||
|
||||
func Combined(dbRegistry model.RegistryService, registries ...model.ReadOnlyRegistryService) model.RegistryService {
|
||||
registries = append(registries, dbRegistry)
|
||||
return &combined{
|
||||
registries: registries,
|
||||
dbRegistry: dbRegistry,
|
||||
}
|
||||
}
|
||||
|
||||
func (c combined) RegistryFind(repo *model.Repo, name string) (*model.Registry, error) {
|
||||
for _, registry := range c.registries {
|
||||
res, err := registry.RegistryFind(repo, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res != nil {
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c combined) RegistryList(repo *model.Repo) ([]*model.Registry, error) {
|
||||
var registeries []*model.Registry
|
||||
for _, registory := range c.registries {
|
||||
list, err := registory.RegistryList(repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registeries = append(registeries, list...)
|
||||
}
|
||||
return registeries, nil
|
||||
}
|
||||
|
||||
func (c combined) RegistryCreate(repo *model.Repo, registry *model.Registry) error {
|
||||
return c.dbRegistry.RegistryCreate(repo, registry)
|
||||
}
|
||||
|
||||
func (c combined) RegistryUpdate(repo *model.Repo, registry *model.Registry) error {
|
||||
return c.dbRegistry.RegistryUpdate(repo, registry)
|
||||
}
|
||||
|
||||
func (c combined) RegistryDelete(repo *model.Repo, name string) error {
|
||||
return c.dbRegistry.RegistryDelete(repo, name)
|
||||
}
|
|
@ -4,32 +4,32 @@ import (
|
|||
"github.com/laszlocph/woodpecker/model"
|
||||
)
|
||||
|
||||
type builtin struct {
|
||||
type db struct {
|
||||
store model.RegistryStore
|
||||
}
|
||||
|
||||
// New returns a new local registry service.
|
||||
func New(store model.RegistryStore) model.RegistryService {
|
||||
return &builtin{store}
|
||||
return &db{store}
|
||||
}
|
||||
|
||||
func (b *builtin) RegistryFind(repo *model.Repo, name string) (*model.Registry, error) {
|
||||
func (b *db) RegistryFind(repo *model.Repo, name string) (*model.Registry, error) {
|
||||
return b.store.RegistryFind(repo, name)
|
||||
}
|
||||
|
||||
func (b *builtin) RegistryList(repo *model.Repo) ([]*model.Registry, error) {
|
||||
func (b *db) RegistryList(repo *model.Repo) ([]*model.Registry, error) {
|
||||
return b.store.RegistryList(repo)
|
||||
}
|
||||
|
||||
func (b *builtin) RegistryCreate(repo *model.Repo, in *model.Registry) error {
|
||||
func (b *db) RegistryCreate(repo *model.Repo, in *model.Registry) error {
|
||||
return b.store.RegistryCreate(in)
|
||||
}
|
||||
|
||||
func (b *builtin) RegistryUpdate(repo *model.Repo, in *model.Registry) error {
|
||||
func (b *db) RegistryUpdate(repo *model.Repo, in *model.Registry) error {
|
||||
return b.store.RegistryUpdate(in)
|
||||
}
|
||||
|
||||
func (b *builtin) RegistryDelete(repo *model.Repo, addr string) error {
|
||||
func (b *db) RegistryDelete(repo *model.Repo, addr string) error {
|
||||
registry, err := b.RegistryFind(repo, addr)
|
||||
if err != nil {
|
||||
return err
|
1
plugins/registry/db_test.go
Normal file
1
plugins/registry/db_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package registry
|
96
plugins/registry/filesystem.go
Normal file
96
plugins/registry/filesystem.go
Normal file
|
@ -0,0 +1,96 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/config/types"
|
||||
"github.com/laszlocph/woodpecker/model"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type filesystem struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func Filesystem(path string) model.ReadOnlyRegistryService {
|
||||
return &filesystem{path}
|
||||
}
|
||||
|
||||
func parseDockerConfig(path string) ([]*model.Registry, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
configFile := configfile.ConfigFile{
|
||||
AuthConfigs: make(map[string]types.AuthConfig),
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(f).Decode(&configFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for addr, ac := range configFile.AuthConfigs {
|
||||
if ac.Auth != "" {
|
||||
ac.Username, ac.Password, err = decodeAuth(ac.Auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ac.Auth = ""
|
||||
ac.ServerAddress = addr
|
||||
configFile.AuthConfigs[addr] = ac
|
||||
}
|
||||
}
|
||||
|
||||
auths := []*model.Registry{}
|
||||
|
||||
for key, auth := range configFile.AuthConfigs {
|
||||
auths = append(auths, &model.Registry{
|
||||
Address: key,
|
||||
Username: auth.Username,
|
||||
Password: auth.Password,
|
||||
})
|
||||
}
|
||||
|
||||
return auths, nil
|
||||
}
|
||||
|
||||
func (b *filesystem) RegistryFind(*model.Repo, string) (*model.Registry, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *filesystem) RegistryList(*model.Repo) ([]*model.Registry, error) {
|
||||
return parseDockerConfig(b.path)
|
||||
}
|
||||
|
||||
// decodeAuth decodes a base64 encoded string and returns username and password
|
||||
func decodeAuth(authStr string) (string, string, error) {
|
||||
if authStr == "" {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
decLen := base64.StdEncoding.DecodedLen(len(authStr))
|
||||
decoded := make([]byte, decLen)
|
||||
authByte := []byte(authStr)
|
||||
n, err := base64.StdEncoding.Decode(decoded, authByte)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if n > decLen {
|
||||
return "", "", fmt.Errorf("Something went wrong decoding auth config")
|
||||
}
|
||||
arr := strings.SplitN(string(decoded), ":", 2)
|
||||
if len(arr) != 2 {
|
||||
return "", "", fmt.Errorf("Invalid auth configuration file")
|
||||
}
|
||||
password := strings.Trim(arr[1], "\x00")
|
||||
return arr[0], password, nil
|
||||
}
|
1
plugins/registry/filesystem_test.go
Normal file
1
plugins/registry/filesystem_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package registry
|
Loading…
Reference in a new issue