You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02: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:
		
							
								
								
									
										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.
										
									
								
							
		Reference in New Issue
	
	Block a user