2022-10-18 01:24:12 +00:00
|
|
|
// Copyright 2022 Woodpecker Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2017-03-05 07:56:08 +00:00
|
|
|
package compiler
|
|
|
|
|
|
|
|
import (
|
2017-03-10 10:58:25 +00:00
|
|
|
"net/url"
|
2017-03-05 07:56:08 +00:00
|
|
|
"os"
|
2017-03-10 10:58:25 +00:00
|
|
|
"path/filepath"
|
2017-03-05 07:56:08 +00:00
|
|
|
"strings"
|
|
|
|
|
2021-09-24 11:18:34 +00:00
|
|
|
"github.com/woodpecker-ci/woodpecker/pipeline/frontend"
|
2017-03-05 07:56:08 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Option configures a compiler option.
|
|
|
|
type Option func(*Compiler)
|
|
|
|
|
2017-03-19 09:07:21 +00:00
|
|
|
// WithOption configures the compiler with the given option if
|
|
|
|
// boolean b evaluates to true.
|
|
|
|
func WithOption(option Option, b bool) Option {
|
|
|
|
switch {
|
|
|
|
case b:
|
|
|
|
return option
|
|
|
|
default:
|
|
|
|
return func(compiler *Compiler) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-08 16:35:56 +00:00
|
|
|
// WithVolumes configures the compiler with default volumes that
|
2017-03-05 07:56:08 +00:00
|
|
|
// are mounted to each container in the pipeline.
|
|
|
|
func WithVolumes(volumes ...string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.volumes = volumes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-06 16:04:25 +00:00
|
|
|
// WithRegistry configures the compiler with registry credentials
|
|
|
|
// that should be used to download images.
|
|
|
|
func WithRegistry(registries ...Registry) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.registries = registries
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-10 10:39:50 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
// WithMetadata configures the compiler with the repository, pipeline
|
2017-03-05 07:56:08 +00:00
|
|
|
// and system metadata. The metadata is used to remove steps from
|
|
|
|
// the compiled pipeline configuration that should be skipped. The
|
|
|
|
// metadata is also added to each container as environment variables.
|
|
|
|
func WithMetadata(metadata frontend.Metadata) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.metadata = metadata
|
|
|
|
|
|
|
|
for k, v := range metadata.Environ() {
|
|
|
|
compiler.env[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithNetrc configures the compiler with netrc authentication
|
|
|
|
// credentials added by default to every container in the pipeline.
|
|
|
|
func WithNetrc(username, password, machine string) Option {
|
2021-11-25 20:30:03 +00:00
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.cloneEnv["CI_NETRC_USERNAME"] = username
|
|
|
|
compiler.cloneEnv["CI_NETRC_PASSWORD"] = password
|
|
|
|
compiler.cloneEnv["CI_NETRC_MACHINE"] = machine
|
|
|
|
}
|
2017-03-05 07:56:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// WithWorkspace configures the compiler with the workspace base
|
|
|
|
// and path. The workspace base is a volume created at runtime and
|
|
|
|
// mounted into all containers in the pipeline. The base and path
|
2022-10-18 01:24:12 +00:00
|
|
|
// are joined to provide the working directory for all pipeline and
|
2017-03-05 07:56:08 +00:00
|
|
|
// plugin steps in the pipeline.
|
|
|
|
func WithWorkspace(base, path string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.base = base
|
|
|
|
compiler.path = path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 10:58:25 +00:00
|
|
|
// WithWorkspaceFromURL configures the compiler with the workspace
|
|
|
|
// base and path based on the repository url.
|
|
|
|
func WithWorkspaceFromURL(base, link string) Option {
|
|
|
|
path := "src"
|
|
|
|
parsed, err := url.Parse(link)
|
|
|
|
if err == nil {
|
2017-09-08 00:43:33 +00:00
|
|
|
path = filepath.Join(path, parsed.Hostname(), parsed.Path)
|
2017-03-10 10:58:25 +00:00
|
|
|
}
|
|
|
|
return WithWorkspace(base, path)
|
|
|
|
}
|
|
|
|
|
2017-03-05 07:56:08 +00:00
|
|
|
// WithEscalated configures the compiler to automatically execute
|
|
|
|
// images as privileged containers if the match the given list.
|
|
|
|
func WithEscalated(images ...string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.escalated = images
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithPrefix configures the compiler with the prefix. The prefix is
|
|
|
|
// used to prefix container, volume and network names to avoid
|
|
|
|
// collision at runtime.
|
|
|
|
func WithPrefix(prefix string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.prefix = prefix
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithLocal configures the compiler with the local flag. The local
|
|
|
|
// flag indicates the pipeline execution is running in a local development
|
|
|
|
// environment with a mounted local working directory.
|
|
|
|
func WithLocal(local bool) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.local = local
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithEnviron configures the compiler with environment variables
|
|
|
|
// added by default to every container in the pipeline.
|
|
|
|
func WithEnviron(env map[string]string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
for k, v := range env {
|
|
|
|
compiler.env[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-22 19:06:28 +00:00
|
|
|
// WithCacher configures the compiler with default cache settings.
|
|
|
|
func WithCacher(cacher Cacher) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.cacher = cacher
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithVolumeCacher configures the compiler with default local volume
|
|
|
|
// caching enabled.
|
|
|
|
func WithVolumeCacher(base string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.cacher = &volumeCacher{base: base}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithS3Cacher configures the compiler with default amazon s3
|
|
|
|
// caching enabled.
|
|
|
|
func WithS3Cacher(access, secret, region, bucket string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.cacher = &s3Cacher{
|
|
|
|
access: access,
|
|
|
|
secret: secret,
|
|
|
|
bucket: bucket,
|
|
|
|
region: region,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 07:56:08 +00:00
|
|
|
// WithProxy configures the compiler with HTTP_PROXY, HTTPS_PROXY,
|
|
|
|
// and NO_PROXY environment variables added by default to every
|
|
|
|
// container in the pipeline.
|
|
|
|
func WithProxy() Option {
|
|
|
|
return WithEnviron(
|
|
|
|
map[string]string{
|
|
|
|
"no_proxy": noProxy,
|
|
|
|
"NO_PROXY": noProxy,
|
|
|
|
"http_proxy": httpProxy,
|
|
|
|
"HTTP_PROXY": httpProxy,
|
|
|
|
"HTTPS_PROXY": httpsProxy,
|
|
|
|
"https_proxy": httpsProxy,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-10-08 16:35:56 +00:00
|
|
|
// WithNetworks configures the compiler with additional networks
|
2022-10-18 01:24:12 +00:00
|
|
|
// to be connected to pipeline containers
|
2017-04-10 16:27:34 +00:00
|
|
|
func WithNetworks(networks ...string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.networks = networks
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-22 19:06:28 +00:00
|
|
|
// WithResourceLimit configures the compiler with default resource limits that
|
|
|
|
// are applied each container in the pipeline.
|
|
|
|
func WithResourceLimit(swap, mem, shmsize, cpuQuota, cpuShares int64, cpuSet string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.reslimit = ResourceLimit{
|
|
|
|
MemSwapLimit: swap,
|
|
|
|
MemLimit: mem,
|
|
|
|
ShmSize: shmsize,
|
|
|
|
CPUQuota: cpuQuota,
|
|
|
|
CPUShares: cpuShares,
|
|
|
|
CPUSet: cpuSet,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-10 16:05:19 +00:00
|
|
|
func WithDefaultCloneImage(cloneImage string) Option {
|
|
|
|
return func(compiler *Compiler) {
|
|
|
|
compiler.defaultCloneImage = cloneImage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-05 07:56:08 +00:00
|
|
|
// TODO(bradrydzewski) consider an alternate approach to
|
|
|
|
// WithProxy where the proxy strings are passed directly
|
|
|
|
// to the function as named parameters.
|
|
|
|
|
|
|
|
// func WithProxy2(http, https, none string) Option {
|
|
|
|
// return WithEnviron(
|
|
|
|
// map[string]string{
|
|
|
|
// "no_proxy": none,
|
|
|
|
// "NO_PROXY": none,
|
|
|
|
// "http_proxy": http,
|
|
|
|
// "HTTP_PROXY": http,
|
|
|
|
// "HTTPS_PROXY": https,
|
|
|
|
// "https_proxy": https,
|
|
|
|
// },
|
|
|
|
// )
|
|
|
|
// }
|
|
|
|
|
|
|
|
var (
|
|
|
|
noProxy = getenv("no_proxy")
|
|
|
|
httpProxy = getenv("https_proxy")
|
|
|
|
httpsProxy = getenv("https_proxy")
|
|
|
|
)
|
|
|
|
|
|
|
|
// getenv returns the named environment variable.
|
|
|
|
func getenv(name string) (value string) {
|
|
|
|
name = strings.ToUpper(name)
|
|
|
|
if value := os.Getenv(name); value != "" {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
name = strings.ToLower(name)
|
|
|
|
if value := os.Getenv(name); value != "" {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|