mirror of https://github.com/docker/compose.git
podTemplate conversion test cases
adapted from compose-on-kubernetes some test need to be fixed, marked as /*FIXME Test*/ Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
f7c86a7d30
commit
f1976eca07
|
@ -30,14 +30,22 @@ func toPodTemplate(serviceConfig types.ServiceConfig, labels map[string]string,
|
|||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
}
|
||||
limits, err := toResource(serviceConfig.Deploy)
|
||||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
|
||||
var limits apiv1.ResourceList = nil
|
||||
if serviceConfig.Deploy != nil && serviceConfig.Deploy.Resources.Limits != nil {
|
||||
limits, err = toResource(serviceConfig.Deploy.Resources.Limits)
|
||||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
}
|
||||
}
|
||||
requests, err := toResource(serviceConfig.Deploy)
|
||||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
var requests apiv1.ResourceList = nil
|
||||
if serviceConfig.Deploy != nil && serviceConfig.Deploy.Resources.Reservations != nil {
|
||||
requests, err = toResource(serviceConfig.Deploy.Resources.Reservations)
|
||||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
}
|
||||
}
|
||||
|
||||
volumes, err := toVolumes(serviceConfig, model)
|
||||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
|
@ -252,12 +260,7 @@ func toRestartPolicy(s types.ServiceConfig) (apiv1.RestartPolicy, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func toResource(deploy *types.DeployConfig) (apiv1.ResourceList, error) {
|
||||
if deploy == nil || deploy.Resources.Limits == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
res := deploy.Resources.Limits
|
||||
func toResource(res *types.Resource) (apiv1.ResourceList, error) {
|
||||
list := make(apiv1.ResourceList)
|
||||
if res.NanoCPUs != "" {
|
||||
cpus, err := resource.ParseQuantity(res.NanoCPUs)
|
||||
|
|
|
@ -0,0 +1,984 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/compose-spec/compose-go/loader"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/helm-prototype/pkg/compose"
|
||||
"github.com/stretchr/testify/assert"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func loadYAML(yaml string) (*compose.Project, error) {
|
||||
dict, err := loader.ParseYAML([]byte(yaml))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
workingDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return compose.NewProject(types.ConfigDetails{
|
||||
WorkingDir: workingDir,
|
||||
ConfigFiles: []types.ConfigFile{
|
||||
{Filename: "compose.yaml", Config: dict},
|
||||
},
|
||||
}, "test")
|
||||
}
|
||||
|
||||
func podTemplate(t *testing.T, yaml string) apiv1.PodTemplateSpec {
|
||||
res, err := podTemplateWithError(yaml)
|
||||
assert.NoError(t, err)
|
||||
return res
|
||||
}
|
||||
|
||||
func podTemplateWithError(yaml string) (apiv1.PodTemplateSpec, error) {
|
||||
project, err := loadYAML(yaml)
|
||||
if err != nil {
|
||||
return apiv1.PodTemplateSpec{}, err
|
||||
}
|
||||
return toPodTemplate(project.Services[0], nil, project)
|
||||
}
|
||||
|
||||
func TestToPodWithDockerSocket(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("on windows, source path validation is broken (and actually, source validation for windows workload is broken too). Skip it for now, as we don't support it yet")
|
||||
return
|
||||
}
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "mount-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
HostPath: &apiv1.HostPathVolumeSource{
|
||||
Path: "/var/run",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "mount-0",
|
||||
MountPath: "/var/run/docker.sock",
|
||||
SubPath: "docker.sock",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func TestToPodWithFunkyCommand(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: basi/node-exporter
|
||||
command: ["-collector.procfs", "/host/proc", "-collector.sysfs", "/host/sys"]
|
||||
`)
|
||||
|
||||
expectedArgs := []string{
|
||||
`-collector.procfs`,
|
||||
`/host/proc`, // ?
|
||||
`-collector.sysfs`,
|
||||
`/host/sys`, // ?
|
||||
}
|
||||
assert.Equal(t, expectedArgs, podTemplate.Spec.Containers[0].Args)
|
||||
}
|
||||
|
||||
func TestToPodWithGlobalVolume(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
db:
|
||||
image: "postgres:9.4"
|
||||
volumes:
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
`)
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "dbdata",
|
||||
MountPath: "/var/lib/postgresql/data",
|
||||
}
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 0)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func TestToPodWithResources(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
db:
|
||||
image: "postgres:9.4"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "0.001"
|
||||
memory: 50Mb
|
||||
reservations:
|
||||
cpus: "0.0001"
|
||||
memory: 20Mb
|
||||
`)
|
||||
|
||||
expectedResourceRequirements := apiv1.ResourceRequirements{
|
||||
Limits: map[apiv1.ResourceName]resource.Quantity{
|
||||
apiv1.ResourceCPU: resource.MustParse("0.001"),
|
||||
apiv1.ResourceMemory: resource.MustParse(fmt.Sprintf("%d", 50*1024*1024)),
|
||||
},
|
||||
Requests: map[apiv1.ResourceName]resource.Quantity{
|
||||
apiv1.ResourceCPU: resource.MustParse("0.0001"),
|
||||
apiv1.ResourceMemory: resource.MustParse(fmt.Sprintf("%d", 20*1024*1024)),
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expectedResourceRequirements, podTemplate.Spec.Containers[0].Resources)
|
||||
}
|
||||
|
||||
func TestToPodWithCapabilities(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
cap_add:
|
||||
- ALL
|
||||
cap_drop:
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
`)
|
||||
|
||||
expectedSecurityContext := &apiv1.SecurityContext{
|
||||
Capabilities: &apiv1.Capabilities{
|
||||
Add: []apiv1.Capability{"ALL"},
|
||||
Drop: []apiv1.Capability{"NET_ADMIN", "SYS_ADMIN"},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedSecurityContext, podTemplate.Spec.Containers[0].SecurityContext)
|
||||
}
|
||||
|
||||
func TestToPodWithReadOnly(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
read_only: true
|
||||
`)
|
||||
|
||||
yes := true
|
||||
expectedSecurityContext := &apiv1.SecurityContext{
|
||||
ReadOnlyRootFilesystem: &yes,
|
||||
}
|
||||
assert.Equal(t, expectedSecurityContext, podTemplate.Spec.Containers[0].SecurityContext)
|
||||
}
|
||||
|
||||
func TestToPodWithPrivileged(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
privileged: true
|
||||
`)
|
||||
|
||||
yes := true
|
||||
expectedSecurityContext := &apiv1.SecurityContext{
|
||||
Privileged: &yes,
|
||||
}
|
||||
assert.Equal(t, expectedSecurityContext, podTemplate.Spec.Containers[0].SecurityContext)
|
||||
}
|
||||
|
||||
func TestToPodWithEnvNilShouldErrorOut(t *testing.T) {
|
||||
_, err := podTemplateWithError(`
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
environment:
|
||||
- SESSION_SECRET
|
||||
`)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestToPodWithEnv(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
environment:
|
||||
- RACK_ENV=development
|
||||
- SHOW=true
|
||||
`)
|
||||
|
||||
expectedEnv := []apiv1.EnvVar{
|
||||
{
|
||||
Name: "RACK_ENV",
|
||||
Value: "development",
|
||||
},
|
||||
{
|
||||
Name: "SHOW",
|
||||
Value: "true",
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedEnv, podTemplate.Spec.Containers[0].Env)
|
||||
}
|
||||
|
||||
func TestToPodWithVolume(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("on windows, source path validation is broken (and actually, source validation for windows workload is broken too). Skip it for now, as we don't support it yet")
|
||||
return
|
||||
}
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
volumes:
|
||||
- /ignore:/ignore
|
||||
- /opt/data:/var/lib/mysql:ro
|
||||
`)
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 2)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 2)
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithRelativeVolumes(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("on windows, source path validation is broken (and actually, source validation for windows workload is broken too). Skip it for now, as we don't support it yet")
|
||||
return
|
||||
}
|
||||
_, err := podTemplateWithError(`
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
volumes:
|
||||
- ./fail:/ignore
|
||||
`)
|
||||
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestToPodWithHealthCheck(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost"]
|
||||
interval: 90s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
`)
|
||||
|
||||
expectedLivenessProbe := &apiv1.Probe{
|
||||
TimeoutSeconds: 10,
|
||||
PeriodSeconds: 90,
|
||||
FailureThreshold: 3,
|
||||
Handler: apiv1.Handler{
|
||||
Exec: &apiv1.ExecAction{
|
||||
Command: []string{"curl", "-f", "http://localhost"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedLivenessProbe, podTemplate.Spec.Containers[0].LivenessProbe)
|
||||
}
|
||||
|
||||
func TestToPodWithShellHealthCheck(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost"]
|
||||
`)
|
||||
|
||||
expectedLivenessProbe := &apiv1.Probe{
|
||||
TimeoutSeconds: 1,
|
||||
PeriodSeconds: 1,
|
||||
FailureThreshold: 3,
|
||||
Handler: apiv1.Handler{
|
||||
Exec: &apiv1.ExecAction{
|
||||
Command: []string{"sh", "-c", "curl -f http://localhost"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedLivenessProbe, podTemplate.Spec.Containers[0].LivenessProbe)
|
||||
}
|
||||
|
||||
func TestToPodWithTargetlessExternalSecret(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
secrets:
|
||||
- my_secret
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "secret-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
Secret: &apiv1.SecretVolumeSource{
|
||||
SecretName: "my_secret",
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file", // TODO: This is the key we assume external secrets use
|
||||
Path: "secret-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "secret-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/run/secrets/my_secret",
|
||||
SubPath: "secret-0",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func TestToPodWithExternalSecret(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
secrets:
|
||||
- source: my_secret
|
||||
target: nginx_secret
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "secret-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
Secret: &apiv1.SecretVolumeSource{
|
||||
SecretName: "my_secret",
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file", // TODO: This is the key we assume external secrets use
|
||||
Path: "secret-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "secret-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/run/secrets/nginx_secret",
|
||||
SubPath: "secret-0",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithFileBasedSecret(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
secrets:
|
||||
- source: my_secret
|
||||
secrets:
|
||||
my_secret:
|
||||
file: ./secret.txt
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "secret-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
Secret: &apiv1.SecretVolumeSource{
|
||||
SecretName: "my_secret",
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "secret.txt",
|
||||
Path: "secret-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "secret-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/run/secrets/my_secret",
|
||||
SubPath: "secret-0",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithTwoFileBasedSecrets(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
secrets:
|
||||
- source: my_secret1
|
||||
- source: my_secret2
|
||||
target: secret2
|
||||
secrets:
|
||||
my_secret1:
|
||||
file: ./secret1.txt
|
||||
my_secret2:
|
||||
file: ./secret2.txt
|
||||
`)
|
||||
|
||||
expectedVolumes := []apiv1.Volume{
|
||||
{
|
||||
Name: "secret-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
Secret: &apiv1.SecretVolumeSource{
|
||||
SecretName: "my_secret1",
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "secret1.txt",
|
||||
Path: "secret-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secret-1",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
Secret: &apiv1.SecretVolumeSource{
|
||||
SecretName: "my_secret2",
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "secret2.txt",
|
||||
Path: "secret-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMounts := []apiv1.VolumeMount{
|
||||
{
|
||||
Name: "secret-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/run/secrets/my_secret1",
|
||||
SubPath: "secret-0",
|
||||
},
|
||||
{
|
||||
Name: "secret-1",
|
||||
ReadOnly: true,
|
||||
MountPath: "/run/secrets/secret2",
|
||||
SubPath: "secret-1",
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedVolumes, podTemplate.Spec.Volumes)
|
||||
assert.Equal(t, expectedMounts, podTemplate.Spec.Containers[0].VolumeMounts)
|
||||
}
|
||||
|
||||
func TestToPodWithTerminationGracePeriod(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
stop_grace_period: 100s
|
||||
`)
|
||||
|
||||
expected := int64(100)
|
||||
assert.Equal(t, &expected, podTemplate.Spec.TerminationGracePeriodSeconds)
|
||||
}
|
||||
|
||||
func TestToPodWithTmpfs(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
tmpfs:
|
||||
- /tmp
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "tmp-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
EmptyDir: &apiv1.EmptyDirVolumeSource{
|
||||
Medium: "Memory",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "tmp-0",
|
||||
MountPath: "/tmp",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func TestToPodWithNumericalUser(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
user: "1000"
|
||||
`)
|
||||
|
||||
userID := int64(1000)
|
||||
|
||||
expectedSecurityContext := &apiv1.SecurityContext{
|
||||
RunAsUser: &userID,
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedSecurityContext, podTemplate.Spec.Containers[0].SecurityContext)
|
||||
}
|
||||
|
||||
func TestToPodWithGitVolume(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
volumes:
|
||||
- source: "git@github.com:moby/moby.git"
|
||||
target: /sources
|
||||
type: git
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "mount-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
GitRepo: &apiv1.GitRepoVolumeSource{
|
||||
Repository: "git@github.com:moby/moby.git",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "mount-0",
|
||||
ReadOnly: false,
|
||||
MountPath: "/sources",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithFileBasedConfig(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
configs:
|
||||
- source: my_config
|
||||
target: /usr/share/nginx/html/index.html
|
||||
uid: "103"
|
||||
gid: "103"
|
||||
mode: 0440
|
||||
configs:
|
||||
my_config:
|
||||
file: ./file.html
|
||||
`)
|
||||
|
||||
mode := int32(0440)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "config-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "my_config",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file.html",
|
||||
Path: "config-0",
|
||||
Mode: &mode,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "config-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/usr/share/nginx/html/index.html",
|
||||
SubPath: "config-0",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithTargetlessFileBasedConfig(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
configs:
|
||||
- my_config
|
||||
configs:
|
||||
my_config:
|
||||
file: ./file.html
|
||||
`)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "config-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "myconfig",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file.html",
|
||||
Path: "config-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "config-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/myconfig",
|
||||
SubPath: "config-0",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func TestToPodWithExternalConfig(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
redis:
|
||||
image: "redis:alpine"
|
||||
configs:
|
||||
- source: my_config
|
||||
target: /usr/share/nginx/html/index.html
|
||||
uid: "103"
|
||||
gid: "103"
|
||||
mode: 0440
|
||||
configs:
|
||||
my_config:
|
||||
external: true
|
||||
`)
|
||||
|
||||
mode := int32(0440)
|
||||
|
||||
expectedVolume := apiv1.Volume{
|
||||
Name: "config-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "my_config",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file", // TODO: This is the key we assume external config use
|
||||
Path: "config-0",
|
||||
Mode: &mode,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMount := apiv1.VolumeMount{
|
||||
Name: "config-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/usr/share/nginx/html/index.html",
|
||||
SubPath: "config-0",
|
||||
}
|
||||
|
||||
assert.Len(t, podTemplate.Spec.Volumes, 1)
|
||||
assert.Len(t, podTemplate.Spec.Containers[0].VolumeMounts, 1)
|
||||
assert.Equal(t, expectedVolume, podTemplate.Spec.Volumes[0])
|
||||
assert.Equal(t, expectedMount, podTemplate.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithTwoConfigsSameMountPoint(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
configs:
|
||||
- source: first
|
||||
target: /data/first.json
|
||||
mode: "0440"
|
||||
- source: second
|
||||
target: /data/second.json
|
||||
mode: "0550"
|
||||
configs:
|
||||
first:
|
||||
file: ./file1
|
||||
secondv:
|
||||
file: ./file2
|
||||
`)
|
||||
|
||||
mode0440 := int32(0440)
|
||||
mode0550 := int32(0550)
|
||||
|
||||
expectedVolumes := []apiv1.Volume{
|
||||
{
|
||||
Name: "config-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "first",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file1",
|
||||
Path: "config-0",
|
||||
Mode: &mode0440,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "config-1",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "second",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file2",
|
||||
Path: "config-1",
|
||||
Mode: &mode0550,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMounts := []apiv1.VolumeMount{
|
||||
{
|
||||
Name: "config-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/data/first.json",
|
||||
SubPath: "config-0",
|
||||
},
|
||||
{
|
||||
Name: "config-1",
|
||||
ReadOnly: true,
|
||||
MountPath: "/data/second.json",
|
||||
SubPath: "config-1",
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedVolumes, podTemplate.Spec.Volumes)
|
||||
assert.Equal(t, expectedMounts, podTemplate.Spec.Containers[0].VolumeMounts)
|
||||
}
|
||||
|
||||
func TestToPodWithTwoExternalConfigsSameMountPoint(t *testing.T) {
|
||||
podTemplate := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
configs:
|
||||
- source: first
|
||||
target: /data/first.json
|
||||
- source: second
|
||||
target: /data/second.json
|
||||
configs:
|
||||
first:
|
||||
file: ./file1
|
||||
second:
|
||||
file: ./file2
|
||||
`)
|
||||
|
||||
expectedVolumes := []apiv1.Volume{
|
||||
{
|
||||
Name: "config-0",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "first",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file",
|
||||
Path: "config-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "config-1",
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
ConfigMap: &apiv1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: apiv1.LocalObjectReference{
|
||||
Name: "second",
|
||||
},
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: "file",
|
||||
Path: "config-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedMounts := []apiv1.VolumeMount{
|
||||
{
|
||||
Name: "config-0",
|
||||
ReadOnly: true,
|
||||
MountPath: "/data/first.json",
|
||||
SubPath: "config-0",
|
||||
},
|
||||
{
|
||||
Name: "config-1",
|
||||
ReadOnly: true,
|
||||
MountPath: "/data/second.json",
|
||||
SubPath: "config-1",
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedVolumes, podTemplate.Spec.Volumes)
|
||||
assert.Equal(t, expectedMounts, podTemplate.Spec.Containers[0].VolumeMounts)
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithPullSecret(t *testing.T) {
|
||||
podTemplateWithSecret := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
x-kubernetes.pull-secret: test-pull-secret
|
||||
`)
|
||||
|
||||
assert.Equal(t, 1, len(podTemplateWithSecret.Spec.ImagePullSecrets))
|
||||
assert.Equal(t, "test-pull-secret", podTemplateWithSecret.Spec.ImagePullSecrets[0].Name)
|
||||
|
||||
podTemplateNoSecret := podTemplate(t, `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
`)
|
||||
|
||||
assert.Nil(t, podTemplateNoSecret.Spec.ImagePullSecrets)
|
||||
}
|
||||
|
||||
func /*FIXME Test*/ToPodWithPullPolicy(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
stack string
|
||||
expectedPolicy apiv1.PullPolicy
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "specific tag",
|
||||
stack: `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:specific
|
||||
`,
|
||||
expectedPolicy: apiv1.PullIfNotPresent,
|
||||
},
|
||||
{
|
||||
name: "latest tag",
|
||||
stack: `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
`,
|
||||
expectedPolicy: apiv1.PullAlways,
|
||||
},
|
||||
{
|
||||
name: "explicit policy",
|
||||
stack: `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:specific
|
||||
x-kubernetes.pull-policy: Never
|
||||
`,
|
||||
expectedPolicy: apiv1.PullNever,
|
||||
},
|
||||
{
|
||||
name: "invalid policy",
|
||||
stack: `
|
||||
version: "3"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx:specific
|
||||
x-kubernetes.pull-policy: Invalid
|
||||
`,
|
||||
expectedError: `invalid pull policy "Invalid", must be "Always", "IfNotPresent" or "Never"`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
pod, err := podTemplateWithError(c.stack)
|
||||
if c.expectedError != "" {
|
||||
assert.EqualError(t, err, c.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pod.Spec.Containers[0].ImagePullPolicy, c.expectedPolicy)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -170,13 +170,13 @@ func defaultMode(mode *uint32) *int32 {
|
|||
return defaultMode
|
||||
}
|
||||
|
||||
func secretVolume(config types.ServiceSecretConfig, topLevelSecret types.SecretConfig, subPath string) *apiv1.VolumeSource {
|
||||
func secretVolume(config types.ServiceSecretConfig, topLevelConfig types.SecretConfig, subPath string) *apiv1.VolumeSource {
|
||||
return &apiv1.VolumeSource{
|
||||
Secret: &apiv1.SecretVolumeSource{
|
||||
SecretName: config.Source,
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: toKey(topLevelSecret.File),
|
||||
Key: toKey(topLevelConfig.File),
|
||||
Path: subPath,
|
||||
Mode: defaultMode(config.Mode),
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue