mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-25 09:50:31 +00:00
b15ca52a63
at the moment we compile a script that we can pipe in as single command this is because of the constrains the docker backend gives us. so we move it into the docker backend and eventually get rid of it altogether
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())
|
|
}
|