diff --git a/client/client.go b/client/client.go index c5a5e565a..443e62ca2 100644 --- a/client/client.go +++ b/client/client.go @@ -115,9 +115,6 @@ type Client interface { // target environment. Deploy(string, string, int, string, map[string]string) (*model.Build, error) - // AgentList returns a list of build agents. - AgentList() ([]*model.Agent, error) - // Registry returns a registry by hostname. Registry(owner, name, hostname string) (*model.Registry, error) diff --git a/client/client_impl.go b/client/client_impl.go index 3621014a1..d1da1adf2 100644 --- a/client/client_impl.go +++ b/client/client_impl.go @@ -53,7 +53,6 @@ const ( pathUsers = "%s/api/users" pathUser = "%s/api/users/%s" pathBuildQueue = "%s/api/builds" - pathAgent = "%s/api/agents" ) type client struct { @@ -367,14 +366,6 @@ func (c *client) Sign(owner, name string, in []byte) ([]byte, error) { return ioutil.ReadAll(rc) } -// AgentList returns a list of build agents. -func (c *client) AgentList() ([]*model.Agent, error) { - var out []*model.Agent - uri := fmt.Sprintf(pathAgent, c.base) - err := c.get(uri, &out) - return out, err -} - // Registry returns a registry by hostname. func (c *client) Registry(owner, name, hostname string) (*model.Registry, error) { out := new(model.Registry) diff --git a/model/agent.go b/model/agent.go deleted file mode 100644 index 1045b393d..000000000 --- a/model/agent.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type Agent struct { - ID int64 `json:"id" meddler:"agent_id,pk"` - Address string `json:"address" meddler:"agent_addr"` - Platform string `json:"platform" meddler:"agent_platform"` - Capacity int `json:"capacity" meddler:"agent_capacity"` - Created int64 `json:"created_at" meddler:"agent_created"` - Updated int64 `json:"updated_at" meddler:"agent_updated"` -} diff --git a/model/approval.go b/model/approval.go new file mode 100644 index 000000000..66d295546 --- /dev/null +++ b/model/approval.go @@ -0,0 +1,17 @@ +package model + +type ( + // ApprovalStore persists approved committers to storage. + ApprovalStore interface { + Approve(*Repo) error + } + + // Approval represents an approved committer. + Approval struct { + Username string `json:"username" meddler:"approval_username"` + Approved bool `json:"approved" meddler:"approval_approved"` + Comments string `json:"comments" meddler:"approval_comments"` + CreatedBy string `json:"created_by" meddler:"approval_created_by"` + CreatedAt int64 `json:"created_at" meddler:"approval_created_at"` + } +) diff --git a/model/gate.go b/model/gate.go new file mode 100644 index 000000000..decc4ad6f --- /dev/null +++ b/model/gate.go @@ -0,0 +1,23 @@ +package model + +// Gated indicates a build is gated and requires approval to proceed. It also +// includes the reason the build was gated. +type Gated struct { + Gated bool `json:"gated"` + Reason string `json:"reason"` +} + +// GateService defines a service for gating builds. +type GateService interface { + Gated(*User, *Repo, *Build) (*Gated, error) +} + +type gateService struct{} + +func (s *gateService) Gated(owner *User, repo *Repo, build *Build) (*Gated, error) { + g := new(Gated) + if repo.IsPrivate && build.Event == EventPull && build.Sender != owner.Login { + g.Gated = true + } + return g, nil +} diff --git a/model/job.go b/model/job.go deleted file mode 100644 index 36c2d2f73..000000000 --- a/model/job.go +++ /dev/null @@ -1,17 +0,0 @@ -package model - -// // swagger:model job -// type Job struct { -// ID int64 `json:"id" meddler:"job_id,pk"` -// BuildID int64 `json:"-" meddler:"job_build_id"` -// NodeID int64 `json:"-" meddler:"job_node_id"` -// Number int `json:"number" meddler:"job_number"` -// Error string `json:"error" meddler:"job_error"` -// Status string `json:"status" meddler:"job_status"` -// ExitCode int `json:"exit_code" meddler:"job_exit_code"` -// Enqueued int64 `json:"enqueued_at" meddler:"job_enqueued"` -// Started int64 `json:"started_at" meddler:"job_started"` -// Finished int64 `json:"finished_at" meddler:"job_finished"` -// -// Environment map[string]string `json:"environment" meddler:"job_environment,json"` -// } diff --git a/server/hook.go b/server/hook.go index dd761e1a8..8fd35b176 100644 --- a/server/hook.go +++ b/server/hook.go @@ -460,12 +460,18 @@ func (b *builder) Build() ([]*buildItem, error) { } secrets := map[string]string{} + var csecrets []compiler.Secret for _, sec := range b.Secs { if !sec.MatchEvent(b.Curr.Event) { continue } if b.Curr.Verified || sec.SkipVerify { secrets[sec.Name] = sec.Value + csecrets = append(csecrets, compiler.Secret{ + Name: sec.Name, + Value: sec.Value, + Match: sec.Images, + }) } } sub := func(name string) string { @@ -521,6 +527,7 @@ func (b *builder) Build() ([]*buildItem, error) { b.Repo.IsPrivate, ), compiler.WithRegistry(registries...), + compiler.WithSecrets(csecrets...), compiler.WithPrefix( fmt.Sprintf( "%d_%d", diff --git a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/compiler.go b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/compiler.go index 097ab4357..7895a588e 100644 --- a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/compiler.go +++ b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/compiler.go @@ -20,6 +20,12 @@ type Registry struct { Token string } +type Secret struct { + Name string + Value string + Match []string +} + // Compiler compiles the yaml type Compiler struct { local bool @@ -31,13 +37,16 @@ type Compiler struct { path string metadata frontend.Metadata registries []Registry + secrets map[string]Secret aliases []string } // New creates a new Compiler with options. func New(opts ...Option) *Compiler { - compiler := new(Compiler) - compiler.env = map[string]string{} + compiler := &Compiler{ + env: map[string]string{}, + secrets: map[string]Secret{}, + } for _, opt := range opts { opt(compiler) } diff --git a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/convert.go b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/convert.go index 218c78ad2..265c5caec 100644 --- a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/convert.go +++ b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/convert.go @@ -3,6 +3,7 @@ package compiler import ( "fmt" "path" + "strings" "github.com/cncd/pipeline/pipeline/backend" "github.com/cncd/pipeline/pipeline/frontend/yaml" @@ -73,7 +74,7 @@ func (c *Compiler) createProcess(name string, container *yaml.Container) *backen if isPlugin(container) { paramsToEnv(container.Vargs, environment) - if imageMatches(container.Image, c.escalated) { + if matchImage(container.Image, c.escalated...) { privileged = true entrypoint = []string{} command = []string{} @@ -102,6 +103,13 @@ func (c *Compiler) createProcess(name string, container *yaml.Container) *backen } } + for _, requested := range container.Secrets.Secrets { + secret, ok := c.secrets[strings.ToLower(requested.Source)] + if ok && (len(secret.Match) == 0 || matchImage(image, secret.Match...)) { + environment[strings.ToUpper(requested.Target)] = secret.Value + } + } + return &backend.Step{ Name: name, Alias: container.Name, @@ -134,16 +142,6 @@ func (c *Compiler) createProcess(name string, container *yaml.Container) *backen } } -func imageMatches(image string, to []string) bool { - image = trimImage(image) - for _, i := range to { - if image == i { - return true - } - } - return false -} - func isPlugin(c *yaml.Container) bool { return len(c.Vargs) != 0 } diff --git a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/option.go b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/option.go index 5d4ac3b25..4ad9f2d42 100644 --- a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/option.go +++ b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/compiler/option.go @@ -39,6 +39,16 @@ func WithRegistry(registries ...Registry) Option { } } +// WithSecret configures the compiler with external secrets +// to be injected into the container at runtime. +func WithSecret(secrets ...Secret) Option { + return func(compiler *Compiler) { + for _, secret := range secrets { + compiler.secrets[strings.ToLower(secret.Name)] = secret + } + } +} + // WithMetadata configutes the compiler with the repostiory, build // and system metadata. The metadata is used to remove steps from // the compiled pipeline configuration that should be skipped. The diff --git a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/container.go b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/container.go index 650e21110..b7b82621c 100644 --- a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/container.go +++ b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/container.go @@ -52,6 +52,7 @@ type ( ShmSize libcompose.MemStringorInt `yaml:"shm_size,omitempty"` Ulimits libcompose.Ulimits `yaml:"ulimits,omitempty"` Volumes libcompose.Volumes `yaml:"volumes,omitempty"` + Secrets Secrets `yaml:"secrets,omitempty"` Constraints Constraints `yaml:"when,omitempty"` Vargs map[string]interface{} `yaml:",inline"` } diff --git a/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/secret.go b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/secret.go new file mode 100644 index 000000000..69ba73dd7 --- /dev/null +++ b/vendor/github.com/cncd/pipeline/pipeline/frontend/yaml/secret.go @@ -0,0 +1,30 @@ +package yaml + +type ( + // Secrets defines a collection of secrets. + Secrets struct { + Secrets []*Secret + } + + // Secret defines a container secret. + Secret struct { + Source string `yaml:"source"` + Target string `yaml:"target"` + } +) + +// UnmarshalYAML implements the Unmarshaller interface. +func (s *Secrets) UnmarshalYAML(unmarshal func(interface{}) error) error { + var strslice []string + err := unmarshal(&strslice) + if err == nil { + for _, str := range strslice { + s.Secrets = append(s.Secrets, &Secret{ + Source: str, + Target: str, + }) + } + return nil + } + return unmarshal(&s.Secrets) +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 3c8e948da..cdc6bf29f 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -28,68 +28,68 @@ { "checksumSHA1": "W3AuK8ocqHwlUajGmQLFvnRhTZE=", "path": "github.com/cncd/pipeline/pipeline", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "Qu2FreqaMr8Yx2bW9O0cxAGgjr0=", "path": "github.com/cncd/pipeline/pipeline/backend", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "0CGXRaYwZhJxGIrGhn8WGpkFqPo=", "path": "github.com/cncd/pipeline/pipeline/backend/docker", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "/8wE+cVb7T4PQZgpLNu0DHzKGuE=", "path": "github.com/cncd/pipeline/pipeline/frontend", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { - "checksumSHA1": "O0sulBQAHJeNLg3lO38Cq5uf/eg=", + "checksumSHA1": "QWs+L3emrt5DDTWvqD6rbMtLKMw=", "path": "github.com/cncd/pipeline/pipeline/frontend/yaml", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { - "checksumSHA1": "4gmWpW2MkXgWGSSvSoRFu1YjGbQ=", + "checksumSHA1": "Bsp5Fq7oc6ZDDX5COo//pajb0kk=", "path": "github.com/cncd/pipeline/pipeline/frontend/yaml/compiler", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "Q0GkNUFamVYIA1Fd8r0A5M6Gx54=", "path": "github.com/cncd/pipeline/pipeline/frontend/yaml/linter", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "kx2sPUIMozPC/g6E4w48h3FfH3k=", "path": "github.com/cncd/pipeline/pipeline/frontend/yaml/matrix", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "2/3f3oNmxXy5kcrRLCFa24Oc9O4=", "path": "github.com/cncd/pipeline/pipeline/interrupt", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "uOjTfke7Qxosrivgz/nVTHeIP5g=", "path": "github.com/cncd/pipeline/pipeline/multipart", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "TP5lK1T8cOKv5QjZ2nqdlYczSTo=", "path": "github.com/cncd/pipeline/pipeline/rpc", - "revision": "087d10834b19bbb8d1665152696ca63883610021", - "revisionTime": "2017-04-06T15:46:03Z" + "revision": "94d637b94d0439ed4853e8089d8a1b1820b67c65", + "revisionTime": "2017-04-09T09:45:58Z" }, { "checksumSHA1": "7Qj1DK0ceAXkYztW0l3+L6sn+V8=",