woodpecker/pipeline/frontend/yaml/container_test.go
6543 e7cfa902a6
Another fix for settings field in pipeline config (#579)
close #578

- adjust to new settings field own pipeline config
- more test coverage
- Fix environment parse of settings
- Fix pipeline schema
2021-12-08 18:17:52 +01:00

258 lines
6.5 KiB
Go

package yaml
import (
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"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 ]
command: bundle exec thin -p 3000
commands:
- go build
- go test
cpu_quota: 11
cpuset: 1,2
cpu_shares: 99
detach: true
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
dns: 8.8.8.8
dns_search: example.com
entrypoint: /code/entrypoint.sh
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
settings:
foo: bar
baz: false
deprecated_setting: fallback
`)
func TestUnmarshalContainer(t *testing.T) {
want := Container{
AuthConfig: AuthConfig{
Username: "janedoe",
Password: "password",
},
CapAdd: []string{"ALL"},
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
Command: types.Command{"bundle", "exec", "thin", "-p", "3000"},
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"},
DNS: types.Stringorslice{"8.8.8.8"},
DNSSearch: types.Stringorslice{"example.com"},
Entrypoint: types.Command{"/code/entrypoint.sh"},
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"},
},
},
Constraints: Constraints{
Branch: Constraint{
Include: []string{"master"},
},
},
Settings: map[string]interface{}{
"foo": "bar",
"baz": false,
},
Vargs: map[string]interface{}{
"deprecated_setting": "fallback",
},
}
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, deprecated_setting: fallback, settings: { normal_setting: true } }",
want: []*Container{
{
Name: "unit_test",
Image: "node",
Settings: map[string]interface{}{
"deprecated_setting": "fallback",
"normal_setting": true,
},
},
},
},
{
from: `publish-agent:
group: bundle
image: print/env
repo: woodpeckerci/woodpecker-agent
dockerfile: docker/Dockerfile.agent
secrets: [docker_username, docker_password]
tag: [next, latest]
dry_run: true
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,
},
Constraints: Constraints{
Event: Constraint{Include: []string{"push"}},
Branch: Constraint{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"),
},
Constraints: Constraints{
Event: Constraint{Include: []string{"push"}},
Branch: Constraint{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
},
},
},
},
}
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
}