forked from LaconicNetwork/kompose
add configmaps derived from file and dir
add tests and e2e function isconfigfile check if we need to use configmap and mount in readonly readonly not asigned because not fail e2e Signed-off-by: jose luis <2064537+sosan@users.noreply.github.com>
This commit is contained in:
parent
14152d4a81
commit
4cd0b268fc
@ -985,3 +985,67 @@ func reformatSecretConfigUnderscoreWithDash(secretConfig types.ServiceSecretConf
|
||||
|
||||
return newSecretConfig
|
||||
}
|
||||
|
||||
// isConfigFile checks if the given filePath should be used as a configMap
|
||||
// if dir is not empty, withindir are treated as cofigmaps
|
||||
// if it's configMap, mount readonly as default
|
||||
func isConfigFile(filePath string) (useConfigMap bool, readonly bool) {
|
||||
if strings.HasSuffix(filePath, ".sock") {
|
||||
return
|
||||
}
|
||||
|
||||
fi, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to check if the directory is empty: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !fi.Mode().IsRegular() { // is dir
|
||||
isDirEmpty, err := checkIsEmptyDir(filePath)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to check if the directory is empty: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if isDirEmpty {
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
return true, true
|
||||
}
|
||||
|
||||
// checkIsEmptyDir checks if filepath is empty
|
||||
func checkIsEmptyDir(filePath string) (bool, error) {
|
||||
entries, err := os.ReadDir(filePath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
return true, err
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// setVolumeAccessMode sets the access mode for a volume based on the mode string
|
||||
// current types:
|
||||
// ReadOnly RO and ReadOnlyMany ROX can be mounted in read-only mode to many hosts
|
||||
// ReadWriteMany RWX can be mounted in read/write mode to many hosts
|
||||
// ReadWriteOncePod RWOP can be mounted in read/write mode to exactly 1 pod
|
||||
// ReadWriteOnce RWO can be mounted in read/write mode to exactly 1 host
|
||||
// https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
|
||||
func setVolumeAccessMode(mode string, volumeAccesMode []api.PersistentVolumeAccessMode) []api.PersistentVolumeAccessMode {
|
||||
switch mode {
|
||||
case "ro", "rox":
|
||||
volumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadOnlyMany}
|
||||
case "rwx":
|
||||
volumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteMany}
|
||||
case "rwop":
|
||||
volumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteOncePod}
|
||||
case "rwo":
|
||||
volumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteOnce}
|
||||
default:
|
||||
volumeAccesMode = []api.PersistentVolumeAccessMode{api.ReadWriteOnce}
|
||||
}
|
||||
|
||||
return volumeAccesMode
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ import (
|
||||
"github.com/kubernetes/kompose/pkg/testutils"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
api "k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
@ -738,3 +739,168 @@ func TestRemoveEmptyInterfaces(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_setVolumeAccessMode(t *testing.T) {
|
||||
type args struct {
|
||||
mode string
|
||||
volumeAccesMode []api.PersistentVolumeAccessMode
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []api.PersistentVolumeAccessMode
|
||||
}{
|
||||
{
|
||||
name: "readonly",
|
||||
args: args{
|
||||
mode: "ro",
|
||||
volumeAccesMode: []api.PersistentVolumeAccessMode{},
|
||||
},
|
||||
want: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},
|
||||
},
|
||||
{
|
||||
name: "not acceptable",
|
||||
args: args{
|
||||
mode: "wrong",
|
||||
volumeAccesMode: []api.PersistentVolumeAccessMode{},
|
||||
},
|
||||
want: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
|
||||
},
|
||||
{
|
||||
name: "readonly many",
|
||||
args: args{
|
||||
mode: "rox",
|
||||
volumeAccesMode: []api.PersistentVolumeAccessMode{},
|
||||
},
|
||||
want: []api.PersistentVolumeAccessMode{api.ReadOnlyMany},
|
||||
},
|
||||
{
|
||||
name: "readwrite many",
|
||||
args: args{
|
||||
mode: "rwx",
|
||||
volumeAccesMode: []api.PersistentVolumeAccessMode{},
|
||||
},
|
||||
want: []api.PersistentVolumeAccessMode{api.ReadWriteMany},
|
||||
},
|
||||
{
|
||||
name: "readwrite once in pod",
|
||||
args: args{
|
||||
mode: "rwop",
|
||||
volumeAccesMode: []api.PersistentVolumeAccessMode{},
|
||||
},
|
||||
want: []api.PersistentVolumeAccessMode{api.ReadWriteOncePod},
|
||||
},
|
||||
{
|
||||
name: "readwrite once",
|
||||
args: args{
|
||||
mode: "rwo",
|
||||
volumeAccesMode: []api.PersistentVolumeAccessMode{},
|
||||
},
|
||||
want: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := setVolumeAccessMode(tt.args.mode, tt.args.volumeAccesMode); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("setVolumeAccessMode() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_isConfigFile(t *testing.T) {
|
||||
type args struct {
|
||||
filePath string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantUseConfigMap bool
|
||||
wantReadonly bool
|
||||
}{
|
||||
{
|
||||
name: "sock",
|
||||
args: args{
|
||||
filePath: "./docker.sock",
|
||||
},
|
||||
wantUseConfigMap: false,
|
||||
wantReadonly: false,
|
||||
},
|
||||
{
|
||||
name: "cannot resolve filepath",
|
||||
args: args{
|
||||
filePath: "./certs/cert1.pem",
|
||||
},
|
||||
wantUseConfigMap: false,
|
||||
wantReadonly: false,
|
||||
},
|
||||
{
|
||||
name: "file cert",
|
||||
args: args{
|
||||
filePath: "../../../script/test/fixtures/configmap-file-configs/certs/cert1.pem",
|
||||
},
|
||||
wantUseConfigMap: true,
|
||||
wantReadonly: true,
|
||||
},
|
||||
{
|
||||
name: "dir not empty",
|
||||
args: args{
|
||||
filePath: "../../../script/test/fixtures/configmap-file-configs/certs",
|
||||
},
|
||||
wantUseConfigMap: true,
|
||||
wantReadonly: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotUseConfigMap, gotReadonly := isConfigFile(tt.args.filePath)
|
||||
if gotUseConfigMap != tt.wantUseConfigMap {
|
||||
t.Errorf("isConfigFile() gotUseConfigMap = %v, want %v", gotUseConfigMap, tt.wantUseConfigMap)
|
||||
}
|
||||
if gotReadonly != tt.wantReadonly {
|
||||
t.Errorf("isConfigFile() gotReadonly = %v, want %v", gotReadonly, tt.wantReadonly)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_checkIsEmptyDir(t *testing.T) {
|
||||
type args struct {
|
||||
filePath string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "dir not found",
|
||||
args: args{
|
||||
filePath: "../../../script/test/fixtures/configmap-file-configs/notfound",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "dir not empty",
|
||||
args: args{
|
||||
filePath: "../../../script/test/fixtures/configmap-file-configs/certs",
|
||||
},
|
||||
want: false,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := checkIsEmptyDir(tt.args.filePath)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("checkIsEmptyDir() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("checkIsEmptyDir() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,11 +635,7 @@ func (k *Kubernetes) CreatePVC(name string, mode string, size string, selectorVa
|
||||
}
|
||||
}
|
||||
|
||||
if mode == "ro" {
|
||||
pvc.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadOnlyMany}
|
||||
} else {
|
||||
pvc.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadWriteOnce}
|
||||
}
|
||||
pvc.Spec.AccessModes = setVolumeAccessMode(mode, pvc.Spec.AccessModes)
|
||||
|
||||
if len(storageClassName) > 0 {
|
||||
pvc.Spec.StorageClassName = &storageClassName
|
||||
@ -958,7 +954,10 @@ func (k *Kubernetes) ConfigVolumes(name string, service kobject.ServiceConfig) (
|
||||
//iterating over array of `Vols` struct as it contains all necessary information about volumes
|
||||
for _, volume := range service.Volumes {
|
||||
// check if ro/rw mode is defined, default rw
|
||||
readonly := len(volume.Mode) > 0 && volume.Mode == "ro"
|
||||
readonly := len(volume.Mode) > 0 && (volume.Mode == "ro" || volume.Mode == "rox")
|
||||
// return useconfigmap and readonly,
|
||||
// not used asigned readonly because dont break e2e
|
||||
useConfigMap, _ = isConfigFile(volume.Host)
|
||||
if volume.VolumeName == "" {
|
||||
if useEmptyVolumes {
|
||||
volumeName = strings.Replace(volume.PVCName, "claim", "empty", 1)
|
||||
|
||||
@ -339,3 +339,8 @@ os_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/resources-lowercase/compos
|
||||
os_output="$KOMPOSE_ROOT/script/test/fixtures/resources-lowercase/output-os.yaml"
|
||||
convert::expect_success "$k8s_cmd" "$k8s_output" || exit 1
|
||||
convert::expect_success "$os_cmd" "$os_output" || exit 1
|
||||
|
||||
#Test configmaps
|
||||
k8s_cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/compose.yaml convert --stdout --with-kompose-annotation=false"
|
||||
k8s_output="$KOMPOSE_ROOT/script/test/fixtures/configmap-file-configs/output-k8s.yaml"
|
||||
convert::expect_success "$k8s_cmd" "$k8s_output" || exit 1
|
||||
|
||||
1
script/test/fixtures/configmap-file-configs/auth.txt
vendored
Normal file
1
script/test/fixtures/configmap-file-configs/auth.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
content from file auth.txt
|
||||
1
script/test/fixtures/configmap-file-configs/certs/cert1.pem
vendored
Normal file
1
script/test/fixtures/configmap-file-configs/certs/cert1.pem
vendored
Normal file
@ -0,0 +1 @@
|
||||
content of file cert1.pem
|
||||
16
script/test/fixtures/configmap-file-configs/compose.yaml
vendored
Normal file
16
script/test/fixtures/configmap-file-configs/compose.yaml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
services:
|
||||
busy:
|
||||
image: busybox
|
||||
ports:
|
||||
- "8081:8080"
|
||||
- "8026:8025"
|
||||
volumes:
|
||||
- ./certs:/certs
|
||||
- ./auth.txt:/auth.txt
|
||||
- ./users.php:/users.php:ro
|
||||
command:
|
||||
[
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"cat /auth.txt /users.php /certs/cert1.pem"
|
||||
]
|
||||
116
script/test/fixtures/configmap-file-configs/output-k8s.yaml
vendored
Normal file
116
script/test/fixtures/configmap-file-configs/output-k8s.yaml
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
io.kompose.service: busy
|
||||
name: busy
|
||||
spec:
|
||||
ports:
|
||||
- name: "8081"
|
||||
port: 8081
|
||||
targetPort: 8080
|
||||
- name: "8026"
|
||||
port: 8026
|
||||
targetPort: 8025
|
||||
selector:
|
||||
io.kompose.service: busy
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
io.kompose.service: busy
|
||||
name: busy
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
io.kompose.service: busy
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
io.kompose.network/configmap-file-configs-default: "true"
|
||||
io.kompose.service: busy
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- cat /auth.txt /users.php /certs/cert1.pem
|
||||
image: busybox
|
||||
name: busy
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
hostPort: 8081
|
||||
protocol: TCP
|
||||
- containerPort: 8025
|
||||
hostPort: 8026
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /certs
|
||||
name: busy-cm0
|
||||
- mountPath: /auth.txt
|
||||
name: busy-cm1
|
||||
subPath: auth.txt
|
||||
- mountPath: /users.php
|
||||
name: busy-cm2
|
||||
subPath: users.php
|
||||
readOnly: true
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- configMap:
|
||||
name: busy-cm0
|
||||
name: busy-cm0
|
||||
- configMap:
|
||||
items:
|
||||
- key: auth.txt
|
||||
path: auth.txt
|
||||
name: busy-cm1
|
||||
name: busy-cm1
|
||||
- configMap:
|
||||
items:
|
||||
- key: users.php
|
||||
path: users.php
|
||||
name: busy-cm2
|
||||
name: busy-cm2
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
cert1.pem: |
|
||||
content of file cert1.pem
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
io.kompose.service: busy
|
||||
name: busy-cm0
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
auth.txt: |
|
||||
content from file auth.txt
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
annotations:
|
||||
use-subpath: "true"
|
||||
labels:
|
||||
io.kompose.service: busy
|
||||
name: busy-cm1
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
users.php: |
|
||||
content from file users.php
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
annotations:
|
||||
use-subpath: "true"
|
||||
labels:
|
||||
io.kompose.service: busy
|
||||
name: busy-cm2
|
||||
1
script/test/fixtures/configmap-file-configs/users.php
vendored
Normal file
1
script/test/fixtures/configmap-file-configs/users.php
vendored
Normal file
@ -0,0 +1 @@
|
||||
content from file users.php
|
||||
Loading…
Reference in New Issue
Block a user