mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-13 12:41:21 +00:00
18d3139e9e
Co-authored-by: Anbraten <anton@ju60.de>
310 lines
7.6 KiB
Go
310 lines
7.6 KiB
Go
package yaml
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/docker/docker/api/types/strslice"
|
|
"github.com/stretchr/testify/assert"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/woodpecker-ci/woodpecker/pipeline/frontend/yaml/constraint"
|
|
"github.com/woodpecker-ci/woodpecker/pipeline/frontend/yaml/types"
|
|
)
|
|
|
|
var containerYaml = []byte(`
|
|
image: golang:latest
|
|
auth_config:
|
|
username: janedoe
|
|
password: password
|
|
cap_add: [ ALL ]
|
|
cap_drop: [ NET_ADMIN, SYS_ADMIN ]
|
|
commands:
|
|
- go build
|
|
- go test
|
|
cpu_quota: 11
|
|
cpuset: 1,2
|
|
cpu_shares: 99
|
|
detach: true
|
|
devices:
|
|
- /dev/ttyUSB0:/dev/ttyUSB0
|
|
directory: example/
|
|
dns: 8.8.8.8
|
|
dns_search: example.com
|
|
environment:
|
|
- RACK_ENV=development
|
|
- SHOW=true
|
|
extra_hosts:
|
|
- somehost:162.242.195.82
|
|
- otherhost:50.31.209.229
|
|
isolation: hyperv
|
|
name: my-build-container
|
|
network_mode: bridge
|
|
networks:
|
|
- some-network
|
|
- other-network
|
|
pull: true
|
|
privileged: true
|
|
labels:
|
|
com.example.type: build
|
|
com.example.team: frontend
|
|
shm_size: 1kb
|
|
mem_limit: 1kb
|
|
memswap_limit: 1kb
|
|
mem_swappiness: 1kb
|
|
volumes:
|
|
- /var/lib/mysql
|
|
- /opt/data:/var/lib/mysql
|
|
- /etc/configs:/etc/configs/:ro
|
|
tmpfs:
|
|
- /var/lib/test
|
|
when:
|
|
- branch: master
|
|
- event: cron
|
|
cron: job1
|
|
settings:
|
|
foo: bar
|
|
baz: false
|
|
`)
|
|
|
|
func TestUnmarshalContainer(t *testing.T) {
|
|
want := Container{
|
|
AuthConfig: AuthConfig{
|
|
Username: "janedoe",
|
|
Password: "password",
|
|
},
|
|
CapAdd: []string{"ALL"},
|
|
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
|
|
Commands: types.StringOrSlice{"go build", "go test"},
|
|
CPUQuota: types.StringorInt(11),
|
|
CPUSet: "1,2",
|
|
CPUShares: types.StringorInt(99),
|
|
Detached: true,
|
|
Devices: []string{"/dev/ttyUSB0:/dev/ttyUSB0"},
|
|
Directory: "example/",
|
|
DNS: types.StringOrSlice{"8.8.8.8"},
|
|
DNSSearch: types.StringOrSlice{"example.com"},
|
|
Environment: types.SliceorMap{"RACK_ENV": "development", "SHOW": "true"},
|
|
ExtraHosts: []string{"somehost:162.242.195.82", "otherhost:50.31.209.229"},
|
|
Image: "golang:latest",
|
|
Isolation: "hyperv",
|
|
Labels: types.SliceorMap{"com.example.type": "build", "com.example.team": "frontend"},
|
|
MemLimit: types.MemStringorInt(1024),
|
|
MemSwapLimit: types.MemStringorInt(1024),
|
|
MemSwappiness: types.MemStringorInt(1024),
|
|
Name: "my-build-container",
|
|
Networks: types.Networks{
|
|
Networks: []*types.Network{
|
|
{Name: "some-network"},
|
|
{Name: "other-network"},
|
|
},
|
|
},
|
|
NetworkMode: "bridge",
|
|
Pull: true,
|
|
Privileged: true,
|
|
ShmSize: types.MemStringorInt(1024),
|
|
Tmpfs: types.StringOrSlice{"/var/lib/test"},
|
|
Volumes: types.Volumes{
|
|
Volumes: []*types.Volume{
|
|
{Source: "", Destination: "/var/lib/mysql"},
|
|
{Source: "/opt/data", Destination: "/var/lib/mysql"},
|
|
{Source: "/etc/configs", Destination: "/etc/configs/", AccessMode: "ro"},
|
|
},
|
|
},
|
|
When: constraint.When{
|
|
Constraints: []constraint.Constraint{
|
|
{
|
|
Branch: constraint.List{
|
|
Include: []string{"master"},
|
|
},
|
|
},
|
|
{
|
|
Event: constraint.List{
|
|
Include: []string{"cron"},
|
|
},
|
|
Cron: constraint.List{
|
|
Include: []string{"job1"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Settings: map[string]interface{}{
|
|
"foo": "bar",
|
|
"baz": false,
|
|
},
|
|
}
|
|
got := Container{}
|
|
err := yaml.Unmarshal(containerYaml, &got)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, want, got, "problem parsing container")
|
|
}
|
|
|
|
// TestUnmarshalContainersErr unmarshals a map of containers. The order is
|
|
// retained and the container key may be used as the container name if a
|
|
// name is not explicitly provided.
|
|
func TestUnmarshalContainers(t *testing.T) {
|
|
testdata := []struct {
|
|
from string
|
|
want []*Container
|
|
}{
|
|
{
|
|
from: "build: { image: golang }",
|
|
want: []*Container{
|
|
{
|
|
Name: "build",
|
|
Image: "golang",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
from: "test: { name: unit_test, image: node, settings: { normal_setting: true } }",
|
|
want: []*Container{
|
|
{
|
|
Name: "unit_test",
|
|
Image: "node",
|
|
Settings: map[string]interface{}{
|
|
"normal_setting": true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
from: `publish-agent:
|
|
group: bundle
|
|
image: print/env
|
|
settings:
|
|
repo: woodpeckerci/woodpecker-agent
|
|
dry_run: true
|
|
dockerfile: docker/Dockerfile.agent
|
|
tag: [next, latest]
|
|
secrets: [docker_username, docker_password]
|
|
when:
|
|
branch: ${CI_REPO_DEFAULT_BRANCH}
|
|
event: push`,
|
|
want: []*Container{
|
|
{
|
|
Name: "publish-agent",
|
|
Image: "print/env",
|
|
Group: "bundle",
|
|
Secrets: Secrets{Secrets: []*Secret{{
|
|
Source: "docker_username",
|
|
Target: "docker_username",
|
|
}, {
|
|
Source: "docker_password",
|
|
Target: "docker_password",
|
|
}}},
|
|
Settings: map[string]interface{}{
|
|
"repo": "woodpeckerci/woodpecker-agent",
|
|
"dockerfile": "docker/Dockerfile.agent",
|
|
"tag": stringsToInterface("next", "latest"),
|
|
"dry_run": true,
|
|
},
|
|
When: constraint.When{
|
|
Constraints: []constraint.Constraint{
|
|
{
|
|
Event: constraint.List{Include: []string{"push"}},
|
|
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
from: `publish-cli:
|
|
group: docker
|
|
image: print/env
|
|
settings:
|
|
repo: woodpeckerci/woodpecker-cli
|
|
dockerfile: docker/Dockerfile.cli
|
|
tag: [next]
|
|
when:
|
|
branch: ${CI_REPO_DEFAULT_BRANCH}
|
|
event: push`,
|
|
want: []*Container{
|
|
{
|
|
Name: "publish-cli",
|
|
Image: "print/env",
|
|
Group: "docker",
|
|
Settings: map[string]interface{}{
|
|
"repo": "woodpeckerci/woodpecker-cli",
|
|
"dockerfile": "docker/Dockerfile.cli",
|
|
"tag": stringsToInterface("next"),
|
|
},
|
|
When: constraint.When{
|
|
Constraints: []constraint.Constraint{
|
|
{
|
|
Event: constraint.List{Include: []string{"push"}},
|
|
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
from: `publish-cli:
|
|
image: print/env
|
|
when:
|
|
- branch: ${CI_REPO_DEFAULT_BRANCH}
|
|
event: push
|
|
- event: pull_request`,
|
|
want: []*Container{
|
|
{
|
|
Name: "publish-cli",
|
|
Image: "print/env",
|
|
When: constraint.When{
|
|
Constraints: []constraint.Constraint{
|
|
{
|
|
Event: constraint.List{Include: []string{"push"}},
|
|
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
|
},
|
|
{
|
|
Event: constraint.List{Include: []string{"pull_request"}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, test := range testdata {
|
|
in := []byte(test.from)
|
|
got := Containers{}
|
|
err := yaml.Unmarshal(in, &got)
|
|
assert.NoError(t, err)
|
|
assert.EqualValues(t, test.want, got.Containers, "problem parsing containers %q", test.from)
|
|
}
|
|
}
|
|
|
|
// TestUnmarshalContainersErr unmarshals a container map where invalid inputs
|
|
// are provided to verify error messages are returned.
|
|
func TestUnmarshalContainersErr(t *testing.T) {
|
|
testdata := []string{
|
|
"foo: { name: [ foo, bar] }",
|
|
"- foo",
|
|
}
|
|
for _, test := range testdata {
|
|
in := []byte(test)
|
|
containers := new(Containers)
|
|
err := yaml.Unmarshal(in, &containers)
|
|
assert.Error(t, err, "wanted error for containers %q", test)
|
|
}
|
|
}
|
|
|
|
func stringsToInterface(val ...string) []interface{} {
|
|
res := make([]interface{}, len(val))
|
|
for i := range val {
|
|
res[i] = val[i]
|
|
}
|
|
return res
|
|
}
|
|
|
|
func TestIsPlugin(t *testing.T) {
|
|
assert.True(t, (&Container{}).IsPlugin())
|
|
assert.True(t, (&Container{
|
|
Commands: types.StringOrSlice(strslice.StrSlice{}),
|
|
}).IsPlugin())
|
|
assert.False(t, (&Container{
|
|
Commands: types.StringOrSlice(strslice.StrSlice{"echo 'this is not a plugin'"}),
|
|
}).IsPlugin())
|
|
}
|