mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-22 16:36:30 +00:00
Parse backend options in backend (#3227)
Currently, backend options are parsed in the yaml parser. This has some issues: - backend specific code should be in the backend folders - it is not possible to add backend options for backends added via addons
This commit is contained in:
parent
d3b57ff0e6
commit
6892a9ca57
17 changed files with 224 additions and 284 deletions
1
go.mod
1
go.mod
|
@ -32,6 +32,7 @@ require (
|
|||
github.com/kinbiko/jsonassert v1.1.1
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/mattn/go-sqlite3 v1.14.20
|
||||
github.com/mitchellh/mapstructure v1.4.2
|
||||
github.com/moby/moby v24.0.9+incompatible
|
||||
github.com/moby/term v0.5.0
|
||||
github.com/muesli/termenv v0.15.2
|
||||
|
|
29
go.sum
29
go.sum
|
@ -67,14 +67,10 @@ github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDror
|
|||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
|
||||
github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v24.0.8+incompatible h1:nZJsIKYXLeYFpsskShljFQcImMXw7zt+3DN/Ay/A6SI=
|
||||
github.com/docker/cli v24.0.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.8+incompatible h1:lbGlhLzolo0tpp+paD0JzOYId072MQmQxZLPevQCFPU=
|
||||
github.com/docker/docker v24.0.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
|
||||
|
@ -89,8 +85,6 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4
|
|||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/expr-lang/expr v1.15.8 h1:FL8+d3rSSP4tmK9o+vKfSMqqpGL8n15pEPiHcnBpxoI=
|
||||
github.com/expr-lang/expr v1.15.8/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ=
|
||||
github.com/expr-lang/expr v1.16.0 h1:BQabx+PbjsL2PEQwkJ4GIn3CcuUh8flduHhJ0lHjWwE=
|
||||
github.com/expr-lang/expr v1.16.0/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
|
@ -149,8 +143,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -306,8 +301,6 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
|
|||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
|
||||
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.20 h1:BAZ50Ns0OFBNxdAqFhbZqdPcht1Xlb16pDCqkq1spr0=
|
||||
github.com/mattn/go-sqlite3 v1.14.20/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
|
@ -316,10 +309,8 @@ github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
|||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
||||
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
||||
github.com/moby/moby v24.0.7+incompatible h1:RrVT5IXBn85mRtFKP+gFwVLCcnNPZIgN3NVRJG9Le+4=
|
||||
github.com/moby/moby v24.0.7+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||
github.com/moby/moby v24.0.8+incompatible h1:lTOrmnT/ZwYrhTbcmkWMTd2Pk65vV+4YuEdIG04shac=
|
||||
github.com/moby/moby v24.0.8+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
||||
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/moby v24.0.9+incompatible h1:Z/hFbZJqC5Fmuf6jesMLdHU71CMAgdiSJ1ZYey+bFmg=
|
||||
github.com/moby/moby v24.0.9+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
|
@ -429,8 +420,6 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
|
|||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
|
||||
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/xanzy/go-gitlab v0.95.2 h1:4p0IirHqEp5f0baK/aQqr4TR57IsD+8e4fuyAA1yi88=
|
||||
github.com/xanzy/go-gitlab v0.95.2/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
||||
github.com/xanzy/go-gitlab v0.96.0 h1:LGkZ+wSNMRtHIBaYE4Hq3dZVjprwHv3Y1+rhKU3WETs=
|
||||
github.com/xanzy/go-gitlab v0.96.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
|
@ -604,8 +593,6 @@ google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAs
|
|||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA=
|
||||
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
|
||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
|
@ -636,16 +623,10 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A=
|
||||
k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA=
|
||||
k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw=
|
||||
k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ=
|
||||
k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
|
||||
k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
|
||||
k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc=
|
||||
k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
|
||||
k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8=
|
||||
k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38=
|
||||
k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A=
|
||||
k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
|
@ -705,7 +686,5 @@ xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohF
|
|||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.3.3/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||
xorm.io/xorm v1.3.6 h1:hfpWHkDIWWqUi8FRF2H2M9O8lO3Ov47rwFcS9gPzPkU=
|
||||
xorm.io/xorm v1.3.6/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||
xorm.io/xorm v1.3.7 h1:mLceAGu0b87r9pD4qXyxGHxifOXIIrAdVcA6k95/osw=
|
||||
xorm.io/xorm v1.3.7/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||
|
|
77
pipeline/backend/kubernetes/backend_options.go
Normal file
77
pipeline/backend/kubernetes/backend_options.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types"
|
||||
)
|
||||
|
||||
// BackendOptions defines all the advanced options for the kubernetes backend
|
||||
type BackendOptions struct {
|
||||
Resources Resources `mapstructure:"resources"`
|
||||
ServiceAccountName string `mapstructure:"serviceAccountName"`
|
||||
NodeSelector map[string]string `mapstructure:"nodeSelector"`
|
||||
Tolerations []Toleration `mapstructure:"tolerations"`
|
||||
SecurityContext *SecurityContext `mapstructure:"securityContext"`
|
||||
}
|
||||
|
||||
// Resources defines two maps for kubernetes resource definitions
|
||||
type Resources struct {
|
||||
Requests map[string]string `mapstructure:"requests"`
|
||||
Limits map[string]string `mapstructure:"limits"`
|
||||
}
|
||||
|
||||
// Toleration defines Kubernetes toleration
|
||||
type Toleration struct {
|
||||
Key string `mapstructure:"key"`
|
||||
Operator TolerationOperator `mapstructure:"operator"`
|
||||
Value string `mapstructure:"value"`
|
||||
Effect TaintEffect `mapstructure:"effect"`
|
||||
TolerationSeconds *int64 `mapstructure:"tolerationSeconds"`
|
||||
}
|
||||
|
||||
type TaintEffect string
|
||||
|
||||
const (
|
||||
TaintEffectNoSchedule TaintEffect = "NoSchedule"
|
||||
TaintEffectPreferNoSchedule TaintEffect = "PreferNoSchedule"
|
||||
TaintEffectNoExecute TaintEffect = "NoExecute"
|
||||
)
|
||||
|
||||
type TolerationOperator string
|
||||
|
||||
const (
|
||||
TolerationOpExists TolerationOperator = "Exists"
|
||||
TolerationOpEqual TolerationOperator = "Equal"
|
||||
)
|
||||
|
||||
type SecurityContext struct {
|
||||
Privileged *bool `mapstructure:"privileged"`
|
||||
RunAsNonRoot *bool `mapstructure:"runAsNonRoot"`
|
||||
RunAsUser *int64 `mapstructure:"runAsUser"`
|
||||
RunAsGroup *int64 `mapstructure:"runAsGroup"`
|
||||
FSGroup *int64 `mapstructure:"fsGroup"`
|
||||
SeccompProfile *SecProfile `mapstructure:"seccompProfile"`
|
||||
ApparmorProfile *SecProfile `mapstructure:"apparmorProfile"`
|
||||
}
|
||||
|
||||
type SecProfile struct {
|
||||
Type SecProfileType `mapstructure:"type"`
|
||||
LocalhostProfile string `mapstructure:"localhostProfile"`
|
||||
}
|
||||
|
||||
type SecProfileType string
|
||||
|
||||
const (
|
||||
SecProfileTypeRuntimeDefault SecProfileType = "RuntimeDefault"
|
||||
SecProfileTypeLocalhost SecProfileType = "Localhost"
|
||||
)
|
||||
|
||||
func parseBackendOptions(step *backend.Step) (BackendOptions, error) {
|
||||
var result BackendOptions
|
||||
if step.BackendOptions == nil {
|
||||
return result, nil
|
||||
}
|
||||
err := mapstructure.Decode(step.BackendOptions[EngineName], &result)
|
||||
return result, err
|
||||
}
|
73
pipeline/backend/kubernetes/backend_options_test.go
Normal file
73
pipeline/backend/kubernetes/backend_options_test.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
backend "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types"
|
||||
)
|
||||
|
||||
func Test_parseBackendOptions(t *testing.T) {
|
||||
got, err := parseBackendOptions(&backend.Step{BackendOptions: nil})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, BackendOptions{}, got)
|
||||
got, err = parseBackendOptions(&backend.Step{BackendOptions: map[string]any{}})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, BackendOptions{}, got)
|
||||
got, err = parseBackendOptions(&backend.Step{
|
||||
BackendOptions: map[string]any{
|
||||
"kubernetes": map[string]any{
|
||||
"nodeSelector": map[string]string{"storage": "ssd"},
|
||||
"serviceAccountName": "wp-svc-acc",
|
||||
"tolerations": []map[string]any{
|
||||
{"key": "net-port", "value": "100Mbit", "effect": TaintEffectNoSchedule},
|
||||
},
|
||||
"resources": map[string]any{
|
||||
"requests": map[string]string{"memory": "128Mi", "cpu": "1000m"},
|
||||
"limits": map[string]string{"memory": "256Mi", "cpu": "2"},
|
||||
},
|
||||
"securityContext": map[string]any{
|
||||
"privileged": newBool(true),
|
||||
"runAsNonRoot": newBool(true),
|
||||
"runAsUser": newInt64(101),
|
||||
"runAsGroup": newInt64(101),
|
||||
"fsGroup": newInt64(101),
|
||||
"seccompProfile": map[string]any{
|
||||
"type": "Localhost",
|
||||
"localhostProfile": "profiles/audit.json",
|
||||
},
|
||||
"apparmorProfile": map[string]any{
|
||||
"type": "Localhost",
|
||||
"localhostProfile": "k8s-apparmor-example-deny-write",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, BackendOptions{
|
||||
NodeSelector: map[string]string{"storage": "ssd"},
|
||||
ServiceAccountName: "wp-svc-acc",
|
||||
Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}},
|
||||
Resources: Resources{
|
||||
Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"},
|
||||
Limits: map[string]string{"memory": "256Mi", "cpu": "2"},
|
||||
},
|
||||
SecurityContext: &SecurityContext{
|
||||
Privileged: newBool(true),
|
||||
RunAsNonRoot: newBool(true),
|
||||
RunAsUser: newInt64(101),
|
||||
RunAsGroup: newInt64(101),
|
||||
FSGroup: newInt64(101),
|
||||
SeccompProfile: &SecProfile{
|
||||
Type: "Localhost",
|
||||
LocalhostProfile: "profiles/audit.json",
|
||||
},
|
||||
ApparmorProfile: &SecProfile{
|
||||
Type: "Localhost",
|
||||
LocalhostProfile: "k8s-apparmor-example-deny-write",
|
||||
},
|
||||
},
|
||||
}, got)
|
||||
}
|
|
@ -172,7 +172,7 @@ func (e *kube) getConfig() *config {
|
|||
return &c
|
||||
}
|
||||
|
||||
// Setup the pipeline environment.
|
||||
// SetupWorkflow sets up the pipeline environment.
|
||||
func (e *kube) SetupWorkflow(ctx context.Context, conf *types.Config, taskUUID string) error {
|
||||
log.Trace().Str("taskUUID", taskUUID).Msgf("Setting up Kubernetes primitives")
|
||||
|
||||
|
@ -183,7 +183,7 @@ func (e *kube) SetupWorkflow(ctx context.Context, conf *types.Config, taskUUID s
|
|||
}
|
||||
}
|
||||
|
||||
extraHosts := []types.HostAlias{}
|
||||
var extraHosts []types.HostAlias
|
||||
for _, stage := range conf.Stages {
|
||||
for _, step := range stage.Steps {
|
||||
if step.Type == types.StepTypeService {
|
||||
|
@ -206,14 +206,19 @@ func (e *kube) SetupWorkflow(ctx context.Context, conf *types.Config, taskUUID s
|
|||
return nil
|
||||
}
|
||||
|
||||
// Start the pipeline step.
|
||||
// StartStep starts the pipeline step.
|
||||
func (e *kube) StartStep(ctx context.Context, step *types.Step, taskUUID string) error {
|
||||
options, err := parseBackendOptions(step)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not parse backend options")
|
||||
}
|
||||
|
||||
log.Trace().Str("taskUUID", taskUUID).Msgf("starting step: %s", step.Name)
|
||||
_, err := startPod(ctx, e, step)
|
||||
_, err = startPod(ctx, e, step, options)
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for the pipeline step to complete and returns
|
||||
// WaitStep waits for the pipeline step to complete and returns
|
||||
// the completion results.
|
||||
func (e *kube) WaitStep(ctx context.Context, step *types.Step, taskUUID string) (*types.State, error) {
|
||||
podName, err := stepToPodName(step)
|
||||
|
@ -291,7 +296,7 @@ func (e *kube) WaitStep(ctx context.Context, step *types.Step, taskUUID string)
|
|||
return bs, nil
|
||||
}
|
||||
|
||||
// Tail the pipeline step logs.
|
||||
// TailStep tails the pipeline step logs.
|
||||
func (e *kube) TailStep(ctx context.Context, step *types.Step, taskUUID string) (io.ReadCloser, error) {
|
||||
podName, err := stepToPodName(step)
|
||||
if err != nil {
|
||||
|
@ -369,7 +374,7 @@ func (e *kube) DestroyStep(ctx context.Context, step *types.Step, taskUUID strin
|
|||
return err
|
||||
}
|
||||
|
||||
// Destroy the pipeline environment.
|
||||
// DestroyWorkflow destroys the pipeline environment.
|
||||
func (e *kube) DestroyWorkflow(ctx context.Context, conf *types.Config, taskUUID string) error {
|
||||
log.Trace().Str("taskUUID", taskUUID).Msg("deleting Kubernetes primitives")
|
||||
|
||||
|
|
|
@ -35,20 +35,20 @@ const (
|
|||
podPrefix = "wp-"
|
||||
)
|
||||
|
||||
func mkPod(step *types.Step, config *config, podName, goos string) (*v1.Pod, error) {
|
||||
func mkPod(step *types.Step, config *config, podName, goos string, options BackendOptions) (*v1.Pod, error) {
|
||||
var err error
|
||||
|
||||
meta, err := podMeta(step, config, podName)
|
||||
meta, err := podMeta(step, config, options, podName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spec, err := podSpec(step, config)
|
||||
spec, err := podSpec(step, config, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
container, err := podContainer(step, podName, goos)
|
||||
container, err := podContainer(step, podName, goos, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func podName(step *types.Step) (string, error) {
|
|||
return dnsName(podPrefix + step.UUID)
|
||||
}
|
||||
|
||||
func podMeta(step *types.Step, config *config, podName string) (metav1.ObjectMeta, error) {
|
||||
func podMeta(step *types.Step, config *config, options BackendOptions, podName string) (metav1.ObjectMeta, error) {
|
||||
var err error
|
||||
meta := metav1.ObjectMeta{
|
||||
Name: podName,
|
||||
|
@ -98,7 +98,7 @@ func podMeta(step *types.Step, config *config, podName string) (metav1.ObjectMet
|
|||
meta.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
securityContext := step.BackendOptions.Kubernetes.SecurityContext
|
||||
securityContext := options.SecurityContext
|
||||
if securityContext != nil {
|
||||
key, value := apparmorAnnotation(podName, securityContext.ApparmorProfile)
|
||||
if key != nil && value != nil {
|
||||
|
@ -113,16 +113,16 @@ func stepLabel(step *types.Step) (string, error) {
|
|||
return toDNSName(step.Name)
|
||||
}
|
||||
|
||||
func podSpec(step *types.Step, config *config) (v1.PodSpec, error) {
|
||||
func podSpec(step *types.Step, config *config, options BackendOptions) (v1.PodSpec, error) {
|
||||
var err error
|
||||
spec := v1.PodSpec{
|
||||
RestartPolicy: v1.RestartPolicyNever,
|
||||
ServiceAccountName: step.BackendOptions.Kubernetes.ServiceAccountName,
|
||||
ServiceAccountName: options.ServiceAccountName,
|
||||
ImagePullSecrets: imagePullSecretsReferences(config.ImagePullSecretNames),
|
||||
HostAliases: hostAliases(step.ExtraHosts),
|
||||
NodeSelector: nodeSelector(step.BackendOptions.Kubernetes.NodeSelector, step.Environment["CI_SYSTEM_PLATFORM"]),
|
||||
Tolerations: tolerations(step.BackendOptions.Kubernetes.Tolerations),
|
||||
SecurityContext: podSecurityContext(step.BackendOptions.Kubernetes.SecurityContext, config.SecurityContext),
|
||||
NodeSelector: nodeSelector(options.NodeSelector, step.Environment["CI_SYSTEM_PLATFORM"]),
|
||||
Tolerations: tolerations(options.Tolerations),
|
||||
SecurityContext: podSecurityContext(options.SecurityContext, config.SecurityContext),
|
||||
}
|
||||
spec.Volumes, err = volumes(step.Volumes)
|
||||
if err != nil {
|
||||
|
@ -132,7 +132,7 @@ func podSpec(step *types.Step, config *config) (v1.PodSpec, error) {
|
|||
return spec, nil
|
||||
}
|
||||
|
||||
func podContainer(step *types.Step, podName, goos string) (v1.Container, error) {
|
||||
func podContainer(step *types.Step, podName, goos string, options BackendOptions) (v1.Container, error) {
|
||||
var err error
|
||||
container := v1.Container{
|
||||
Name: podName,
|
||||
|
@ -156,9 +156,9 @@ func podContainer(step *types.Step, podName, goos string) (v1.Container, error)
|
|||
|
||||
container.Env = mapToEnvVars(step.Environment)
|
||||
container.Ports = containerPorts(step.Ports)
|
||||
container.SecurityContext = containerSecurityContext(step.BackendOptions.Kubernetes.SecurityContext, step.Privileged)
|
||||
container.SecurityContext = containerSecurityContext(options.SecurityContext, step.Privileged)
|
||||
|
||||
container.Resources, err = resourceRequirements(step.BackendOptions.Kubernetes.Resources)
|
||||
container.Resources, err = resourceRequirements(options.Resources)
|
||||
if err != nil {
|
||||
return container, err
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ func imagePullSecretsReference(imagePullSecretName string) v1.LocalObjectReferen
|
|||
}
|
||||
}
|
||||
|
||||
func resourceRequirements(resources types.Resources) (v1.ResourceRequirements, error) {
|
||||
func resourceRequirements(resources Resources) (v1.ResourceRequirements, error) {
|
||||
var err error
|
||||
requirements := v1.ResourceRequirements{}
|
||||
|
||||
|
@ -315,7 +315,7 @@ func nodeSelector(backendNodeSelector map[string]string, platform string) map[st
|
|||
return nodeSelector
|
||||
}
|
||||
|
||||
func tolerations(backendTolerations []types.Toleration) []v1.Toleration {
|
||||
func tolerations(backendTolerations []Toleration) []v1.Toleration {
|
||||
var tolerations []v1.Toleration
|
||||
|
||||
if len(backendTolerations) > 0 {
|
||||
|
@ -329,7 +329,7 @@ func tolerations(backendTolerations []types.Toleration) []v1.Toleration {
|
|||
return tolerations
|
||||
}
|
||||
|
||||
func toleration(backendToleration types.Toleration) v1.Toleration {
|
||||
func toleration(backendToleration Toleration) v1.Toleration {
|
||||
return v1.Toleration{
|
||||
Key: backendToleration.Key,
|
||||
Operator: v1.TolerationOperator(backendToleration.Operator),
|
||||
|
@ -339,7 +339,7 @@ func toleration(backendToleration types.Toleration) v1.Toleration {
|
|||
}
|
||||
}
|
||||
|
||||
func podSecurityContext(sc *types.SecurityContext, secCtxConf SecurityContextConfig) *v1.PodSecurityContext {
|
||||
func podSecurityContext(sc *SecurityContext, secCtxConf SecurityContextConfig) *v1.PodSecurityContext {
|
||||
var (
|
||||
nonRoot *bool
|
||||
user *int64
|
||||
|
@ -381,7 +381,7 @@ func podSecurityContext(sc *types.SecurityContext, secCtxConf SecurityContextCon
|
|||
return securityContext
|
||||
}
|
||||
|
||||
func seccompProfile(scp *types.SecProfile) *v1.SeccompProfile {
|
||||
func seccompProfile(scp *SecProfile) *v1.SeccompProfile {
|
||||
if scp == nil || len(scp.Type) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ func seccompProfile(scp *types.SecProfile) *v1.SeccompProfile {
|
|||
return seccompProfile
|
||||
}
|
||||
|
||||
func containerSecurityContext(sc *types.SecurityContext, stepPrivileged bool) *v1.SecurityContext {
|
||||
func containerSecurityContext(sc *SecurityContext, stepPrivileged bool) *v1.SecurityContext {
|
||||
var privileged *bool
|
||||
|
||||
if sc != nil && sc.Privileged != nil && *sc.Privileged {
|
||||
|
@ -417,7 +417,7 @@ func containerSecurityContext(sc *types.SecurityContext, stepPrivileged bool) *v
|
|||
return securityContext
|
||||
}
|
||||
|
||||
func apparmorAnnotation(containerName string, scp *types.SecProfile) (*string, *string) {
|
||||
func apparmorAnnotation(containerName string, scp *SecProfile) (*string, *string) {
|
||||
if scp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -428,12 +428,12 @@ func apparmorAnnotation(containerName string, scp *types.SecProfile) (*string, *
|
|||
profilePath string
|
||||
)
|
||||
|
||||
if scp.Type == types.SecProfileTypeRuntimeDefault {
|
||||
if scp.Type == SecProfileTypeRuntimeDefault {
|
||||
profileType = "runtime"
|
||||
profilePath = "default"
|
||||
}
|
||||
|
||||
if scp.Type == types.SecProfileTypeLocalhost {
|
||||
if scp.Type == SecProfileTypeLocalhost {
|
||||
profileType = "localhost"
|
||||
profilePath = scp.LocalhostProfile
|
||||
}
|
||||
|
@ -458,13 +458,13 @@ func mapToEnvVars(m map[string]string) []v1.EnvVar {
|
|||
return ev
|
||||
}
|
||||
|
||||
func startPod(ctx context.Context, engine *kube, step *types.Step) (*v1.Pod, error) {
|
||||
func startPod(ctx context.Context, engine *kube, step *types.Step, options BackendOptions) (*v1.Pod, error) {
|
||||
podName, err := stepToPodName(step)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
engineConfig := engine.getConfig()
|
||||
pod, err := mkPod(step, engineConfig, podName, engine.goos)
|
||||
pod, err := mkPod(step, engineConfig, podName, engine.goos, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ func TestTinyPod(t *testing.T) {
|
|||
Environment: map[string]string{"CI": "woodpecker"},
|
||||
}, &config{
|
||||
Namespace: "woodpecker",
|
||||
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64")
|
||||
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
podJSON, err := json.Marshal(pod)
|
||||
|
@ -297,17 +297,17 @@ func TestFullPod(t *testing.T) {
|
|||
{Number: 2345, Protocol: "tcp"},
|
||||
{Number: 3456, Protocol: "udp"},
|
||||
}
|
||||
secCtx := types.SecurityContext{
|
||||
secCtx := SecurityContext{
|
||||
Privileged: newBool(true),
|
||||
RunAsNonRoot: newBool(true),
|
||||
RunAsUser: newInt64(101),
|
||||
RunAsGroup: newInt64(101),
|
||||
FSGroup: newInt64(101),
|
||||
SeccompProfile: &types.SecProfile{
|
||||
SeccompProfile: &SecProfile{
|
||||
Type: "Localhost",
|
||||
LocalhostProfile: "profiles/audit.json",
|
||||
},
|
||||
ApparmorProfile: &types.SecProfile{
|
||||
ApparmorProfile: &SecProfile{
|
||||
Type: "Localhost",
|
||||
LocalhostProfile: "k8s-apparmor-example-deny-write",
|
||||
},
|
||||
|
@ -324,25 +324,22 @@ func TestFullPod(t *testing.T) {
|
|||
Environment: map[string]string{"CGO": "0"},
|
||||
ExtraHosts: hostAliases,
|
||||
Ports: ports,
|
||||
BackendOptions: types.BackendOptions{
|
||||
Kubernetes: types.KubernetesBackendOptions{
|
||||
NodeSelector: map[string]string{"storage": "ssd"},
|
||||
ServiceAccountName: "wp-svc-acc",
|
||||
Tolerations: []types.Toleration{{Key: "net-port", Value: "100Mbit", Effect: types.TaintEffectNoSchedule}},
|
||||
Resources: types.Resources{
|
||||
Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"},
|
||||
Limits: map[string]string{"memory": "256Mi", "cpu": "2"},
|
||||
},
|
||||
SecurityContext: &secCtx,
|
||||
},
|
||||
},
|
||||
}, &config{
|
||||
Namespace: "woodpecker",
|
||||
ImagePullSecretNames: []string{"regcred", "another-pull-secret"},
|
||||
PodLabels: map[string]string{"app": "test"},
|
||||
PodAnnotations: map[string]string{"apps.kubernetes.io/pod-index": "0"},
|
||||
SecurityContext: SecurityContextConfig{RunAsNonRoot: false},
|
||||
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64")
|
||||
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{
|
||||
NodeSelector: map[string]string{"storage": "ssd"},
|
||||
ServiceAccountName: "wp-svc-acc",
|
||||
Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}},
|
||||
Resources: Resources{
|
||||
Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"},
|
||||
Limits: map[string]string{"memory": "256Mi", "cpu": "2"},
|
||||
},
|
||||
SecurityContext: &secCtx,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
podJSON, err := json.Marshal(pod)
|
||||
|
|
|
@ -60,8 +60,3 @@ type Backend interface {
|
|||
type BackendInfo struct {
|
||||
Platform string
|
||||
}
|
||||
|
||||
// BackendOptions defines advanced options for specific backends
|
||||
type BackendOptions struct {
|
||||
Kubernetes KubernetesBackendOptions `json:"kubernetes,omitempty"`
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright 2023 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.
|
||||
|
||||
package types
|
||||
|
||||
// KubernetesBackendOptions defines all the advanced options for the kubernetes backend
|
||||
type KubernetesBackendOptions struct {
|
||||
Resources Resources `json:"resouces,omitempty"`
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||
Tolerations []Toleration `json:"tolerations,omitempty"`
|
||||
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
|
||||
}
|
||||
|
||||
// Resources defines two maps for kubernetes resource definitions
|
||||
type Resources struct {
|
||||
Requests map[string]string `json:"requests,omitempty"`
|
||||
Limits map[string]string `json:"limits,omitempty"`
|
||||
}
|
||||
|
||||
// Defines Kubernetes toleration
|
||||
type Toleration struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Operator TolerationOperator `json:"operator,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Effect TaintEffect `json:"effect,omitempty"`
|
||||
TolerationSeconds *int64 `json:"tolerationSeconds,omitempty"`
|
||||
}
|
||||
|
||||
type TaintEffect string
|
||||
|
||||
const (
|
||||
TaintEffectNoSchedule TaintEffect = "NoSchedule"
|
||||
TaintEffectPreferNoSchedule TaintEffect = "PreferNoSchedule"
|
||||
TaintEffectNoExecute TaintEffect = "NoExecute"
|
||||
)
|
||||
|
||||
type TolerationOperator string
|
||||
|
||||
const (
|
||||
TolerationOpExists TolerationOperator = "Exists"
|
||||
TolerationOpEqual TolerationOperator = "Equal"
|
||||
)
|
||||
|
||||
type SecurityContext struct {
|
||||
Privileged *bool `json:"privileged,omitempty"`
|
||||
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
|
||||
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||
RunAsGroup *int64 `json:"runAsGroup,omitempty"`
|
||||
FSGroup *int64 `json:"fsGroup,omitempty"`
|
||||
SeccompProfile *SecProfile `json:"seccompProfile,omitempty"`
|
||||
ApparmorProfile *SecProfile `json:"apparmorProfile,omitempty"`
|
||||
}
|
||||
|
||||
type SecProfile struct {
|
||||
Type SecProfileType `json:"type,omitempty"`
|
||||
LocalhostProfile string `json:"localhostProfile,omitempty"`
|
||||
}
|
||||
|
||||
type SecProfileType string
|
||||
|
||||
const (
|
||||
SecProfileTypeRuntimeDefault SecProfileType = "RuntimeDefault"
|
||||
SecProfileTypeLocalhost SecProfileType = "Localhost"
|
||||
)
|
|
@ -46,7 +46,7 @@ type Step struct {
|
|||
AuthConfig Auth `json:"auth_config,omitempty"`
|
||||
NetworkMode string `json:"network_mode,omitempty"`
|
||||
Ports []Port `json:"ports,omitempty"`
|
||||
BackendOptions BackendOptions `json:"backend_options,omitempty"`
|
||||
BackendOptions map[string]any `json:"backend_options,omitempty"`
|
||||
}
|
||||
|
||||
// StepType identifies the type of step
|
||||
|
|
|
@ -34,7 +34,6 @@ type Registry struct {
|
|||
Hostname string
|
||||
Username string
|
||||
Password string
|
||||
Email string
|
||||
Token string
|
||||
}
|
||||
|
||||
|
|
|
@ -134,11 +134,6 @@ func (c *Compiler) createProcess(container *yaml_types.Container, stepType backe
|
|||
}
|
||||
}
|
||||
|
||||
// Advanced backend settings
|
||||
backendOptions := backend_types.BackendOptions{
|
||||
Kubernetes: convertKubernetesBackendOptions(&container.BackendOptions.Kubernetes),
|
||||
}
|
||||
|
||||
memSwapLimit := int64(container.MemSwapLimit)
|
||||
if c.reslimit.MemSwapLimit != 0 {
|
||||
memSwapLimit = c.reslimit.MemSwapLimit
|
||||
|
@ -214,7 +209,7 @@ func (c *Compiler) createProcess(container *yaml_types.Container, stepType backe
|
|||
Failure: failure,
|
||||
NetworkMode: networkMode,
|
||||
Ports: ports,
|
||||
BackendOptions: backendOptions,
|
||||
BackendOptions: container.BackendOptions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -240,52 +235,3 @@ func convertPort(portDef string) (backend_types.Port, error) {
|
|||
|
||||
return port, nil
|
||||
}
|
||||
|
||||
func convertKubernetesBackendOptions(kubeOpt *yaml_types.KubernetesBackendOptions) backend_types.KubernetesBackendOptions {
|
||||
resources := backend_types.Resources{
|
||||
Limits: kubeOpt.Resources.Limits,
|
||||
Requests: kubeOpt.Resources.Requests,
|
||||
}
|
||||
|
||||
var tolerations []backend_types.Toleration
|
||||
for _, t := range kubeOpt.Tolerations {
|
||||
tolerations = append(tolerations, backend_types.Toleration{
|
||||
Key: t.Key,
|
||||
Operator: backend_types.TolerationOperator(t.Operator),
|
||||
Value: t.Value,
|
||||
Effect: backend_types.TaintEffect(t.Effect),
|
||||
TolerationSeconds: t.TolerationSeconds,
|
||||
})
|
||||
}
|
||||
|
||||
var securityContext *backend_types.SecurityContext
|
||||
if kubeOpt.SecurityContext != nil {
|
||||
securityContext = &backend_types.SecurityContext{
|
||||
Privileged: kubeOpt.SecurityContext.Privileged,
|
||||
RunAsNonRoot: kubeOpt.SecurityContext.RunAsNonRoot,
|
||||
RunAsUser: kubeOpt.SecurityContext.RunAsUser,
|
||||
RunAsGroup: kubeOpt.SecurityContext.RunAsGroup,
|
||||
FSGroup: kubeOpt.SecurityContext.FSGroup,
|
||||
}
|
||||
if kubeOpt.SecurityContext.SeccompProfile != nil {
|
||||
securityContext.SeccompProfile = &backend_types.SecProfile{
|
||||
Type: backend_types.SecProfileType(kubeOpt.SecurityContext.SeccompProfile.Type),
|
||||
LocalhostProfile: kubeOpt.SecurityContext.SeccompProfile.LocalhostProfile,
|
||||
}
|
||||
}
|
||||
if kubeOpt.SecurityContext.ApparmorProfile != nil {
|
||||
securityContext.ApparmorProfile = &backend_types.SecProfile{
|
||||
Type: backend_types.SecProfileType(kubeOpt.SecurityContext.ApparmorProfile.Type),
|
||||
LocalhostProfile: kubeOpt.SecurityContext.ApparmorProfile.LocalhostProfile,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return backend_types.KubernetesBackendOptions{
|
||||
Resources: resources,
|
||||
ServiceAccountName: kubeOpt.ServiceAccountName,
|
||||
NodeSelector: kubeOpt.NodeSelector,
|
||||
Tolerations: tolerations,
|
||||
SecurityContext: securityContext,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
steps:
|
||||
build:
|
||||
image: golang
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
backend_options:
|
||||
custom_backend:
|
||||
option1: xyz
|
||||
option2: [1, 2, 3]
|
|
@ -111,6 +111,11 @@ func TestSchema(t *testing.T) {
|
|||
testFile: ".woodpecker/test-dag.yaml",
|
||||
fail: false,
|
||||
},
|
||||
{
|
||||
name: "Custom backend",
|
||||
testFile: ".woodpecker/test-custom-backend.yaml",
|
||||
fail: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testTable {
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
// Copyright 2023 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.
|
||||
|
||||
package types
|
||||
|
||||
// BackendOptions are advanced options for specific backends
|
||||
type BackendOptions struct {
|
||||
Kubernetes KubernetesBackendOptions `yaml:"kubernetes,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesBackendOptions struct {
|
||||
Resources Resources `yaml:"resources,omitempty"`
|
||||
ServiceAccountName string `yaml:"serviceAccountName,omitempty"`
|
||||
NodeSelector map[string]string `yaml:"nodeSelector,omitempty"`
|
||||
Tolerations []Toleration `yaml:"tolerations,omitempty"`
|
||||
SecurityContext *SecurityContext `yaml:"securityContext,omitempty"`
|
||||
}
|
||||
|
||||
type Resources struct {
|
||||
Requests map[string]string `yaml:"requests,omitempty"`
|
||||
Limits map[string]string `yaml:"limits,omitempty"`
|
||||
}
|
||||
|
||||
type Toleration struct {
|
||||
Key string `yaml:"key,omitempty"`
|
||||
Operator TolerationOperator `yaml:"operator,omitempty"`
|
||||
Value string `yaml:"value,omitempty"`
|
||||
Effect TaintEffect `yaml:"effect,omitempty"`
|
||||
TolerationSeconds *int64 `yaml:"tolerationSeconds,omitempty"`
|
||||
}
|
||||
|
||||
type TaintEffect string
|
||||
|
||||
const (
|
||||
TaintEffectNoSchedule TaintEffect = "NoSchedule"
|
||||
TaintEffectPreferNoSchedule TaintEffect = "PreferNoSchedule"
|
||||
TaintEffectNoExecute TaintEffect = "NoExecute"
|
||||
)
|
||||
|
||||
type TolerationOperator string
|
||||
|
||||
const (
|
||||
TolerationOpExists TolerationOperator = "Exists"
|
||||
TolerationOpEqual TolerationOperator = "Equal"
|
||||
)
|
||||
|
||||
type SecurityContext struct {
|
||||
Privileged *bool `yaml:"privileged,omitempty"`
|
||||
RunAsNonRoot *bool `yaml:"runAsNonRoot,omitempty"`
|
||||
RunAsUser *int64 `yaml:"runAsUser,omitempty"`
|
||||
RunAsGroup *int64 `yaml:"runAsGroup,omitempty"`
|
||||
FSGroup *int64 `yaml:"fsGroup,omitempty"`
|
||||
SeccompProfile *SecProfile `yaml:"seccompProfile,omitempty"`
|
||||
ApparmorProfile *SecProfile `yaml:"apparmorProfile,omitempty"`
|
||||
}
|
||||
|
||||
type SecProfile struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
LocalhostProfile string `yaml:"localhostProfile,omitempty"`
|
||||
}
|
|
@ -33,7 +33,7 @@ type (
|
|||
|
||||
// Container defines a container.
|
||||
Container struct {
|
||||
BackendOptions BackendOptions `yaml:"backend_options,omitempty"`
|
||||
BackendOptions map[string]any `yaml:"backend_options,omitempty"`
|
||||
Commands base.StringOrSlice `yaml:"commands,omitempty"`
|
||||
Entrypoint base.StringOrSlice `yaml:"entrypoint,omitempty"`
|
||||
Detached bool `yaml:"detach,omitempty"`
|
||||
|
|
BIN
server/store/datastore/migration/testfiles/tmp_4282431288
Normal file
BIN
server/store/datastore/migration/testfiles/tmp_4282431288
Normal file
Binary file not shown.
Loading…
Reference in a new issue