mirror of
https://github.com/containers/podman
synced 2024-10-19 16:54:07 +00:00
66944baad6
In k8s a persistent volume claim (PVC) allow pods to define a volume by referencing the name of a PVC. The PVC basically contains criterias that k8s then use to select which storage source it will use for the volume. Podman only provide one abtracted storage, the named volumes, and create them if they don't exists yet. So this patch simply use a volume with the name of the PVC. Signed-off-by: Alban Bedel <albeu@free.fr>
1552 lines
44 KiB
Go
1552 lines
44 KiB
Go
package integration
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"text/template"
|
|
|
|
. "github.com/containers/podman/v2/test/utils"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var unknownKindYaml = `
|
|
apiVerson: v1
|
|
kind: UnknownKind
|
|
metadata:
|
|
labels:
|
|
app: app1
|
|
name: unknown
|
|
spec:
|
|
hostname: unknown
|
|
`
|
|
|
|
var configMapYamlTemplate = `
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: {{ .Name }}
|
|
data:
|
|
{{ with .Data }}
|
|
{{ range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{ end }}
|
|
{{ end }}
|
|
`
|
|
|
|
var podYamlTemplate = `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
creationTimestamp: "2019-07-17T14:44:08Z"
|
|
name: {{ .Name }}
|
|
labels:
|
|
app: {{ .Name }}
|
|
{{ with .Labels }}
|
|
{{ range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ with .Annotations }}
|
|
annotations:
|
|
{{ range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
spec:
|
|
restartPolicy: {{ .RestartPolicy }}
|
|
hostname: {{ .Hostname }}
|
|
hostAliases:
|
|
{{ range .HostAliases }}
|
|
- hostnames:
|
|
{{ range .HostName }}
|
|
- {{ . }}
|
|
{{ end }}
|
|
ip: {{ .IP }}
|
|
{{ end }}
|
|
containers:
|
|
{{ with .Ctrs }}
|
|
{{ range . }}
|
|
- command:
|
|
{{ range .Cmd }}
|
|
- {{.}}
|
|
{{ end }}
|
|
args:
|
|
{{ range .Arg }}
|
|
- {{.}}
|
|
{{ end }}
|
|
env:
|
|
- name: PATH
|
|
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
- name: TERM
|
|
value: xterm
|
|
- name: HOSTNAME
|
|
- name: container
|
|
value: podman
|
|
{{ range .Env }}
|
|
- name: {{ .Name }}
|
|
{{ if (eq .ValueFrom "configmap") }}
|
|
valueFrom:
|
|
configMapKeyRef:
|
|
name: {{ .RefName }}
|
|
key: {{ .RefKey }}
|
|
{{ else }}
|
|
value: {{ .Value }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ with .EnvFrom}}
|
|
envFrom:
|
|
{{ range . }}
|
|
{{ if (eq .From "configmap") }}
|
|
- configMapRef:
|
|
name: {{ .Name }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
image: {{ .Image }}
|
|
name: {{ .Name }}
|
|
imagePullPolicy: {{ .PullPolicy }}
|
|
{{- if or .CpuRequest .CpuLimit .MemoryRequest .MemoryLimit }}
|
|
resources:
|
|
{{- if or .CpuRequest .MemoryRequest }}
|
|
requests:
|
|
{{if .CpuRequest }}cpu: {{ .CpuRequest }}{{ end }}
|
|
{{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }}
|
|
{{- end }}
|
|
{{- if or .CpuLimit .MemoryLimit }}
|
|
limits:
|
|
{{if .CpuLimit }}cpu: {{ .CpuLimit }}{{ end }}
|
|
{{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{ if .SecurityContext }}
|
|
securityContext:
|
|
allowPrivilegeEscalation: true
|
|
{{ if .Caps }}
|
|
capabilities:
|
|
{{ with .CapAdd }}
|
|
add:
|
|
{{ range . }}
|
|
- {{.}}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ with .CapDrop }}
|
|
drop:
|
|
{{ range . }}
|
|
- {{.}}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
privileged: false
|
|
readOnlyRootFilesystem: false
|
|
ports:
|
|
- containerPort: {{ .Port }}
|
|
hostIP: {{ .HostIP }}
|
|
hostPort: {{ .Port }}
|
|
protocol: TCP
|
|
workingDir: /
|
|
volumeMounts:
|
|
{{ if .VolumeMount }}
|
|
- name: {{.VolumeName}}
|
|
mountPath: {{ .VolumeMountPath }}
|
|
readonly: {{.VolumeReadOnly}}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ with .Volumes }}
|
|
volumes:
|
|
{{ range . }}
|
|
- name: {{ .Name }}
|
|
{{- if (eq .VolumeType "HostPath") }}
|
|
hostPath:
|
|
path: {{ .HostPath.Path }}
|
|
type: {{ .HostPath.Type }}
|
|
{{- end }}
|
|
{{- if (eq .VolumeType "PersistentVolumeClaim") }}
|
|
persistentVolumeClaim:
|
|
claimName: {{ .PersistentVolumeClaim.ClaimName }}
|
|
{{- end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
status: {}
|
|
`
|
|
|
|
var deploymentYamlTemplate = `
|
|
apiVersion: v1
|
|
kind: Deployment
|
|
metadata:
|
|
creationTimestamp: "2019-07-17T14:44:08Z"
|
|
name: {{ .Name }}
|
|
labels:
|
|
app: {{ .Name }}
|
|
{{ with .Labels }}
|
|
{{ range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ with .Annotations }}
|
|
annotations:
|
|
{{ range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{ end }}
|
|
{{ end }}
|
|
|
|
spec:
|
|
replicas: {{ .Replicas }}
|
|
selector:
|
|
matchLabels:
|
|
app: {{ .Name }}
|
|
template:
|
|
{{ with .PodTemplate }}
|
|
metadata:
|
|
labels:
|
|
app: {{ .Name }}
|
|
{{- with .Labels }}{{ range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{- end }}{{ end }}
|
|
{{- with .Annotations }}
|
|
annotations:
|
|
{{- range $key, $value := . }}
|
|
{{ $key }}: {{ $value }}
|
|
{{- end }}
|
|
{{- end }}
|
|
spec:
|
|
restartPolicy: {{ .RestartPolicy }}
|
|
hostname: {{ .Hostname }}
|
|
containers:
|
|
{{ with .Ctrs }}
|
|
{{ range . }}
|
|
- command:
|
|
{{ range .Cmd }}
|
|
- {{.}}
|
|
{{ end }}
|
|
args:
|
|
{{ range .Arg }}
|
|
- {{.}}
|
|
{{ end }}
|
|
env:
|
|
- name: PATH
|
|
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
- name: TERM
|
|
value: xterm
|
|
- name: HOSTNAME
|
|
- name: container
|
|
value: podman
|
|
image: {{ .Image }}
|
|
name: {{ .Name }}
|
|
imagePullPolicy: {{ .PullPolicy }}
|
|
{{- if or .CpuRequest .CpuLimit .MemoryRequest .MemoryLimit }}
|
|
resources:
|
|
{{- if or .CpuRequest .MemoryRequest }}
|
|
requests:
|
|
{{if .CpuRequest }}cpu: {{ .CpuRequest }}{{ end }}
|
|
{{if .MemoryRequest }}memory: {{ .MemoryRequest }}{{ end }}
|
|
{{- end }}
|
|
{{- if or .CpuLimit .MemoryLimit }}
|
|
limits:
|
|
{{if .CpuLimit }}cpu: {{ .CpuLimit }}{{ end }}
|
|
{{if .MemoryLimit }}memory: {{ .MemoryLimit }}{{ end }}
|
|
{{- end }}
|
|
{{- end }}
|
|
{{ if .SecurityContext }}
|
|
securityContext:
|
|
allowPrivilegeEscalation: true
|
|
{{ if .Caps }}
|
|
capabilities:
|
|
{{ with .CapAdd }}
|
|
add:
|
|
{{ range . }}
|
|
- {{.}}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ with .CapDrop }}
|
|
drop:
|
|
{{ range . }}
|
|
- {{.}}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
privileged: false
|
|
readOnlyRootFilesystem: false
|
|
workingDir: /
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
{{ end }}
|
|
`
|
|
|
|
var (
|
|
defaultCtrName = "testCtr"
|
|
defaultCtrCmd = []string{"top"}
|
|
defaultCtrArg = []string{"-d", "1.5"}
|
|
defaultCtrImage = ALPINE
|
|
defaultPodName = "testPod"
|
|
defaultVolName = "testVol"
|
|
defaultDeploymentName = "testDeployment"
|
|
defaultConfigMapName = "testConfigMap"
|
|
seccompPwdEPERM = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`)
|
|
// CPU Period in ms
|
|
defaultCPUPeriod = 100
|
|
)
|
|
|
|
func writeYaml(content string, fileName string) error {
|
|
f, err := os.Create(fileName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
_, err = f.WriteString(content)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func generateKubeYaml(kind string, object interface{}, pathname string) error {
|
|
var yamlTemplate string
|
|
templateBytes := &bytes.Buffer{}
|
|
|
|
switch kind {
|
|
case "configmap":
|
|
yamlTemplate = configMapYamlTemplate
|
|
case "pod":
|
|
yamlTemplate = podYamlTemplate
|
|
case "deployment":
|
|
yamlTemplate = deploymentYamlTemplate
|
|
default:
|
|
return fmt.Errorf("unsupported kubernetes kind")
|
|
}
|
|
|
|
t, err := template.New(kind).Parse(yamlTemplate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := t.Execute(templateBytes, object); err != nil {
|
|
return err
|
|
}
|
|
|
|
return writeYaml(templateBytes.String(), pathname)
|
|
}
|
|
|
|
// ConfigMap describes the options a kube yaml can be configured at configmap level
|
|
type ConfigMap struct {
|
|
Name string
|
|
Data map[string]string
|
|
}
|
|
|
|
func getConfigMap(options ...configMapOption) *ConfigMap {
|
|
cm := ConfigMap{
|
|
Name: defaultConfigMapName,
|
|
Data: map[string]string{},
|
|
}
|
|
|
|
for _, option := range options {
|
|
option(&cm)
|
|
}
|
|
|
|
return &cm
|
|
}
|
|
|
|
type configMapOption func(*ConfigMap)
|
|
|
|
func withConfigMapName(name string) configMapOption {
|
|
return func(configmap *ConfigMap) {
|
|
configmap.Name = name
|
|
}
|
|
}
|
|
|
|
func withConfigMapData(k, v string) configMapOption {
|
|
return func(configmap *ConfigMap) {
|
|
configmap.Data[k] = v
|
|
}
|
|
}
|
|
|
|
// Pod describes the options a kube yaml can be configured at pod level
|
|
type Pod struct {
|
|
Name string
|
|
RestartPolicy string
|
|
Hostname string
|
|
HostAliases []HostAlias
|
|
Ctrs []*Ctr
|
|
Volumes []*Volume
|
|
Labels map[string]string
|
|
Annotations map[string]string
|
|
}
|
|
|
|
type HostAlias struct {
|
|
IP string
|
|
HostName []string
|
|
}
|
|
|
|
// getPod takes a list of podOptions and returns a pod with sane defaults
|
|
// and the configured options
|
|
// if no containers are added, it will add the default container
|
|
func getPod(options ...podOption) *Pod {
|
|
p := Pod{
|
|
Name: defaultPodName,
|
|
RestartPolicy: "Never",
|
|
Hostname: "",
|
|
HostAliases: nil,
|
|
Ctrs: make([]*Ctr, 0),
|
|
Volumes: make([]*Volume, 0),
|
|
Labels: make(map[string]string),
|
|
Annotations: make(map[string]string),
|
|
}
|
|
for _, option := range options {
|
|
option(&p)
|
|
}
|
|
if len(p.Ctrs) == 0 {
|
|
p.Ctrs = []*Ctr{getCtr()}
|
|
}
|
|
return &p
|
|
}
|
|
|
|
type podOption func(*Pod)
|
|
|
|
func withPodName(name string) podOption {
|
|
return func(pod *Pod) {
|
|
pod.Name = name
|
|
}
|
|
}
|
|
|
|
func withHostname(h string) podOption {
|
|
return func(pod *Pod) {
|
|
pod.Hostname = h
|
|
}
|
|
}
|
|
|
|
func withHostAliases(ip string, host []string) podOption {
|
|
return func(pod *Pod) {
|
|
pod.HostAliases = append(pod.HostAliases, HostAlias{
|
|
IP: ip,
|
|
HostName: host,
|
|
})
|
|
}
|
|
}
|
|
|
|
func withCtr(c *Ctr) podOption {
|
|
return func(pod *Pod) {
|
|
pod.Ctrs = append(pod.Ctrs, c)
|
|
}
|
|
}
|
|
|
|
func withRestartPolicy(policy string) podOption {
|
|
return func(pod *Pod) {
|
|
pod.RestartPolicy = policy
|
|
}
|
|
}
|
|
|
|
func withLabel(k, v string) podOption {
|
|
return func(pod *Pod) {
|
|
pod.Labels[k] = v
|
|
}
|
|
}
|
|
|
|
func withAnnotation(k, v string) podOption {
|
|
return func(pod *Pod) {
|
|
pod.Annotations[k] = v
|
|
}
|
|
}
|
|
|
|
func withVolume(v *Volume) podOption {
|
|
return func(pod *Pod) {
|
|
pod.Volumes = append(pod.Volumes, v)
|
|
}
|
|
}
|
|
|
|
// Deployment describes the options a kube yaml can be configured at deployment level
|
|
type Deployment struct {
|
|
Name string
|
|
Replicas int32
|
|
Labels map[string]string
|
|
Annotations map[string]string
|
|
PodTemplate *Pod
|
|
}
|
|
|
|
func getDeployment(options ...deploymentOption) *Deployment {
|
|
d := Deployment{
|
|
Name: defaultDeploymentName,
|
|
Replicas: 1,
|
|
Labels: make(map[string]string),
|
|
Annotations: make(map[string]string),
|
|
PodTemplate: getPod(),
|
|
}
|
|
for _, option := range options {
|
|
option(&d)
|
|
}
|
|
|
|
return &d
|
|
}
|
|
|
|
type deploymentOption func(*Deployment)
|
|
|
|
func withDeploymentLabel(k, v string) deploymentOption {
|
|
return func(deployment *Deployment) {
|
|
deployment.Labels[k] = v
|
|
}
|
|
}
|
|
|
|
func withDeploymentAnnotation(k, v string) deploymentOption {
|
|
return func(deployment *Deployment) {
|
|
deployment.Annotations[k] = v
|
|
}
|
|
}
|
|
|
|
func withPod(pod *Pod) deploymentOption {
|
|
return func(d *Deployment) {
|
|
d.PodTemplate = pod
|
|
}
|
|
}
|
|
|
|
func withReplicas(replicas int32) deploymentOption {
|
|
return func(d *Deployment) {
|
|
d.Replicas = replicas
|
|
}
|
|
}
|
|
|
|
// getPodNamesInDeployment returns list of Pod objects
|
|
// with just their name set, so that it can be passed around
|
|
// and into getCtrNameInPod for ease of testing
|
|
func getPodNamesInDeployment(d *Deployment) []Pod {
|
|
var pods []Pod
|
|
var i int32
|
|
|
|
for i = 0; i < d.Replicas; i++ {
|
|
p := Pod{}
|
|
p.Name = fmt.Sprintf("%s-pod-%d", d.Name, i)
|
|
pods = append(pods, p)
|
|
}
|
|
|
|
return pods
|
|
}
|
|
|
|
// Ctr describes the options a kube yaml can be configured at container level
|
|
type Ctr struct {
|
|
Name string
|
|
Image string
|
|
Cmd []string
|
|
Arg []string
|
|
CpuRequest string
|
|
CpuLimit string
|
|
MemoryRequest string
|
|
MemoryLimit string
|
|
SecurityContext bool
|
|
Caps bool
|
|
CapAdd []string
|
|
CapDrop []string
|
|
PullPolicy string
|
|
HostIP string
|
|
Port string
|
|
VolumeMount bool
|
|
VolumeMountPath string
|
|
VolumeName string
|
|
VolumeReadOnly bool
|
|
Env []Env
|
|
EnvFrom []EnvFrom
|
|
}
|
|
|
|
// getCtr takes a list of ctrOptions and returns a Ctr with sane defaults
|
|
// and the configured options
|
|
func getCtr(options ...ctrOption) *Ctr {
|
|
c := Ctr{
|
|
Name: defaultCtrName,
|
|
Image: defaultCtrImage,
|
|
Cmd: defaultCtrCmd,
|
|
Arg: defaultCtrArg,
|
|
SecurityContext: true,
|
|
Caps: false,
|
|
CapAdd: nil,
|
|
CapDrop: nil,
|
|
PullPolicy: "",
|
|
HostIP: "",
|
|
Port: "",
|
|
VolumeMount: false,
|
|
VolumeMountPath: "",
|
|
VolumeName: "",
|
|
VolumeReadOnly: false,
|
|
Env: []Env{},
|
|
EnvFrom: []EnvFrom{},
|
|
}
|
|
for _, option := range options {
|
|
option(&c)
|
|
}
|
|
return &c
|
|
}
|
|
|
|
type ctrOption func(*Ctr)
|
|
|
|
func withCmd(cmd []string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.Cmd = cmd
|
|
}
|
|
}
|
|
|
|
func withArg(arg []string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.Arg = arg
|
|
}
|
|
}
|
|
|
|
func withImage(img string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.Image = img
|
|
}
|
|
}
|
|
|
|
func withCpuRequest(request string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.CpuRequest = request
|
|
}
|
|
}
|
|
|
|
func withCpuLimit(limit string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.CpuLimit = limit
|
|
}
|
|
}
|
|
|
|
func withMemoryRequest(request string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.MemoryRequest = request
|
|
}
|
|
}
|
|
|
|
func withMemoryLimit(limit string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.MemoryLimit = limit
|
|
}
|
|
}
|
|
|
|
func withSecurityContext(sc bool) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.SecurityContext = sc
|
|
}
|
|
}
|
|
|
|
func withCapAdd(caps []string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.CapAdd = caps
|
|
c.Caps = true
|
|
}
|
|
}
|
|
|
|
func withCapDrop(caps []string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.CapDrop = caps
|
|
c.Caps = true
|
|
}
|
|
}
|
|
|
|
func withPullPolicy(policy string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.PullPolicy = policy
|
|
}
|
|
}
|
|
|
|
func withHostIP(ip string, port string) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.HostIP = ip
|
|
c.Port = port
|
|
}
|
|
}
|
|
|
|
func withVolumeMount(mountPath string, readonly bool) ctrOption {
|
|
return func(c *Ctr) {
|
|
c.VolumeMountPath = mountPath
|
|
c.VolumeName = defaultVolName
|
|
c.VolumeReadOnly = readonly
|
|
c.VolumeMount = true
|
|
}
|
|
}
|
|
|
|
func withEnv(name, value, valueFrom, refName, refKey string) ctrOption {
|
|
return func(c *Ctr) {
|
|
e := Env{
|
|
Name: name,
|
|
Value: value,
|
|
ValueFrom: valueFrom,
|
|
RefName: refName,
|
|
RefKey: refKey,
|
|
}
|
|
|
|
c.Env = append(c.Env, e)
|
|
}
|
|
}
|
|
|
|
func withEnvFrom(name, from string) ctrOption {
|
|
return func(c *Ctr) {
|
|
e := EnvFrom{
|
|
Name: name,
|
|
From: from,
|
|
}
|
|
|
|
c.EnvFrom = append(c.EnvFrom, e)
|
|
}
|
|
}
|
|
|
|
func getCtrNameInPod(pod *Pod) string {
|
|
return fmt.Sprintf("%s-%s", pod.Name, defaultCtrName)
|
|
}
|
|
|
|
type HostPath struct {
|
|
Path string
|
|
Type string
|
|
}
|
|
|
|
type PersistentVolumeClaim struct {
|
|
ClaimName string
|
|
}
|
|
|
|
type Volume struct {
|
|
VolumeType string
|
|
Name string
|
|
HostPath
|
|
PersistentVolumeClaim
|
|
}
|
|
|
|
// getHostPathVolume takes a type and a location for a HostPath
|
|
// volume giving it a default name of volName
|
|
func getHostPathVolume(vType, vPath string) *Volume {
|
|
return &Volume{
|
|
VolumeType: "HostPath",
|
|
Name: defaultVolName,
|
|
HostPath: HostPath{
|
|
Path: vPath,
|
|
Type: vType,
|
|
},
|
|
}
|
|
}
|
|
|
|
// getHostPathVolume takes a name for a Persistentvolumeclaim
|
|
// volume giving it a default name of volName
|
|
func getPersistentVolumeClaimVolume(vName string) *Volume {
|
|
return &Volume{
|
|
VolumeType: "PersistentVolumeClaim",
|
|
Name: defaultVolName,
|
|
PersistentVolumeClaim: PersistentVolumeClaim{
|
|
ClaimName: vName,
|
|
},
|
|
}
|
|
}
|
|
|
|
type Env struct {
|
|
Name string
|
|
Value string
|
|
ValueFrom string
|
|
RefName string
|
|
RefKey string
|
|
}
|
|
|
|
type EnvFrom struct {
|
|
Name string
|
|
From string
|
|
}
|
|
|
|
func milliCPUToQuota(milliCPU string) int {
|
|
milli, _ := strconv.Atoi(strings.Trim(milliCPU, "m"))
|
|
return milli * defaultCPUPeriod
|
|
}
|
|
|
|
var _ = Describe("Podman play kube", func() {
|
|
var (
|
|
tempdir string
|
|
err error
|
|
podmanTest *PodmanTestIntegration
|
|
kubeYaml string
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
tempdir, err = CreateTempDirInTempDir()
|
|
if err != nil {
|
|
os.Exit(1)
|
|
}
|
|
podmanTest = PodmanTestCreate(tempdir)
|
|
podmanTest.Setup()
|
|
podmanTest.SeedImages()
|
|
|
|
kubeYaml = filepath.Join(podmanTest.TempDir, "kube.yaml")
|
|
})
|
|
|
|
AfterEach(func() {
|
|
podmanTest.Cleanup()
|
|
f := CurrentGinkgoTestDescription()
|
|
processTestResult(f)
|
|
})
|
|
|
|
It("podman play kube fail with yaml of unsupported kind", func() {
|
|
err := writeYaml(unknownKindYaml, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Not(Equal(0)))
|
|
|
|
})
|
|
|
|
It("podman play kube fail with nonexist authfile", func() {
|
|
err := generateKubeYaml("pod", getPod(), kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", "--authfile", "/tmp/nonexist", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Not(Equal(0)))
|
|
|
|
})
|
|
|
|
It("podman play kube test correct command", func() {
|
|
pod := getPod()
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
// Use the defined command to override the image's command
|
|
correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
|
|
})
|
|
|
|
It("podman play kube test correct command with only set command in yaml file", func() {
|
|
pod := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg(nil))))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
// Use the defined command to override the image's command, and don't set the args
|
|
// so the full command in result should not contains the image's command
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`))
|
|
})
|
|
|
|
It("podman play kube test correct command with only set args in yaml file", func() {
|
|
pod := getPod(withCtr(getCtr(withImage(redis), withCmd(nil), withArg([]string{"echo", "hello"}))))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
// this image's ENTRYPOINT is called `docker-entrypoint.sh`
|
|
// so result should be `docker-entrypoint.sh + withArg(...)`
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(`[docker-entrypoint.sh echo hello]`))
|
|
})
|
|
|
|
It("podman play kube test correct output", func() {
|
|
p := getPod(withCtr(getCtr(withCmd([]string{"echo", "hello"}), withArg([]string{"world"}))))
|
|
|
|
err := generateKubeYaml("pod", p, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(p)})
|
|
logs.WaitWithDefaultTimeout()
|
|
Expect(logs.ExitCode()).To(Equal(0))
|
|
Expect(logs.OutputToString()).To(ContainSubstring("hello world"))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(p), "--format", "'{{ .Config.Cmd }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello world]`))
|
|
})
|
|
|
|
It("podman play kube test restartPolicy", func() {
|
|
// podName, set, expect
|
|
testSli := [][]string{
|
|
{"testPod1", "", "always"}, // Default equal to always
|
|
{"testPod2", "Always", "always"},
|
|
{"testPod3", "OnFailure", "on-failure"},
|
|
{"testPod4", "Never", "no"},
|
|
}
|
|
for _, v := range testSli {
|
|
pod := getPod(withPodName(v[0]), withRestartPolicy(v[1]))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{.HostConfig.RestartPolicy.Name}}"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(Equal(v[2]))
|
|
}
|
|
})
|
|
|
|
It("podman play kube test env value from configmap", func() {
|
|
SkipIfRemote("configmap list is not supported as a param")
|
|
cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
|
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO", "foo"))
|
|
err := generateKubeYaml("configmap", cm, cmYamlPathname)
|
|
Expect(err).To(BeNil())
|
|
|
|
pod := getPod(withCtr(getCtr(withEnv("FOO", "", "configmap", "foo", "FOO"))))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=foo`))
|
|
})
|
|
|
|
It("podman play kube test get all key-value pairs from configmap as envs", func() {
|
|
SkipIfRemote("configmap list is not supported as a param")
|
|
cmYamlPathname := filepath.Join(podmanTest.TempDir, "foo-cm.yaml")
|
|
cm := getConfigMap(withConfigMapName("foo"), withConfigMapData("FOO1", "foo1"), withConfigMapData("FOO2", "foo2"))
|
|
err := generateKubeYaml("configmap", cm, cmYamlPathname)
|
|
Expect(err).To(BeNil())
|
|
|
|
pod := getPod(withCtr(getCtr(withEnvFrom("foo", "configmap"))))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml, "--configmap", cmYamlPathname})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Env }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO1=foo1`))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO2=foo2`))
|
|
})
|
|
|
|
It("podman play kube test hostname", func() {
|
|
pod := getPod()
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(Equal(defaultPodName))
|
|
})
|
|
|
|
It("podman play kube test with customized hostname", func() {
|
|
hostname := "myhostname"
|
|
pod := getPod(withHostname(hostname))
|
|
err := generateKubeYaml("pod", getPod(withHostname(hostname)), kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .Config.Hostname }}"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(Equal(hostname))
|
|
})
|
|
|
|
It("podman play kube test HostAliases", func() {
|
|
pod := getPod(withHostAliases("192.168.1.2", []string{
|
|
"test1.podman.io",
|
|
"test2.podman.io",
|
|
}),
|
|
withHostAliases("192.168.1.3", []string{
|
|
"test3.podman.io",
|
|
"test4.podman.io",
|
|
}),
|
|
)
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", pod.Name, "--format", "{{ .InfraConfig.HostAdd}}"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).
|
|
To(Equal("[test1.podman.io:192.168.1.2 test2.podman.io:192.168.1.2 test3.podman.io:192.168.1.3 test4.podman.io:192.168.1.3]"))
|
|
})
|
|
|
|
It("podman play kube cap add", func() {
|
|
capAdd := "CAP_SYS_ADMIN"
|
|
ctr := getCtr(withCapAdd([]string{capAdd}), withCmd([]string{"cat", "/proc/self/status"}), withArg(nil))
|
|
|
|
pod := getPod(withCtr(ctr))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(capAdd))
|
|
})
|
|
|
|
It("podman play kube cap drop", func() {
|
|
capDrop := "CAP_CHOWN"
|
|
ctr := getCtr(withCapDrop([]string{capDrop}))
|
|
|
|
pod := getPod(withCtr(ctr))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(capDrop))
|
|
})
|
|
|
|
It("podman play kube no security context", func() {
|
|
// expect play kube to not fail if no security context is specified
|
|
pod := getPod(withCtr(getCtr(withSecurityContext(false))))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
})
|
|
|
|
It("podman play kube seccomp container level", func() {
|
|
SkipIfRemote("podman-remote does not support --seccomp-profile-root flag")
|
|
// expect play kube is expected to set a seccomp label if it's applied as an annotation
|
|
jsonFile, err := podmanTest.CreateSeccompJson(seccompPwdEPERM)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
Skip("Failed to prepare seccomp.json for test.")
|
|
}
|
|
|
|
ctrAnnotation := "container.seccomp.security.alpha.kubernetes.io/" + defaultCtrName
|
|
ctr := getCtr(withCmd([]string{"pwd"}), withArg(nil))
|
|
|
|
pod := getPod(withCtr(ctr), withAnnotation(ctrAnnotation, "localhost/"+filepath.Base(jsonFile)))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
// CreateSeccompJson will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look
|
|
kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)})
|
|
logs.WaitWithDefaultTimeout()
|
|
Expect(logs.ExitCode()).To(Equal(0))
|
|
Expect(logs.OutputToString()).To(ContainSubstring("Operation not permitted"))
|
|
})
|
|
|
|
It("podman play kube seccomp pod level", func() {
|
|
SkipIfRemote("podman-remote does not support --seccomp-profile-root flag")
|
|
// expect play kube is expected to set a seccomp label if it's applied as an annotation
|
|
jsonFile, err := podmanTest.CreateSeccompJson(seccompPwdEPERM)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
Skip("Failed to prepare seccomp.json for test.")
|
|
}
|
|
defer os.Remove(jsonFile)
|
|
|
|
ctr := getCtr(withCmd([]string{"pwd"}), withArg(nil))
|
|
|
|
pod := getPod(withCtr(ctr), withAnnotation("seccomp.security.alpha.kubernetes.io/pod", "localhost/"+filepath.Base(jsonFile)))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
// CreateSeccompJson will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look
|
|
kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
logs := podmanTest.Podman([]string{"logs", getCtrNameInPod(pod)})
|
|
logs.WaitWithDefaultTimeout()
|
|
Expect(logs.ExitCode()).To(Equal(0))
|
|
Expect(logs.OutputToString()).To(ContainSubstring("Operation not permitted"))
|
|
})
|
|
|
|
It("podman play kube with pull policy of never should be 125", func() {
|
|
ctr := getCtr(withPullPolicy("never"), withImage(BB_GLIBC))
|
|
err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(125))
|
|
})
|
|
|
|
It("podman play kube with pull policy of missing", func() {
|
|
ctr := getCtr(withPullPolicy("missing"), withImage(BB))
|
|
err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
})
|
|
|
|
It("podman play kube with pull always", func() {
|
|
oldBB := "quay.io/libpod/busybox:1.30.1"
|
|
pull := podmanTest.Podman([]string{"pull", oldBB})
|
|
pull.WaitWithDefaultTimeout()
|
|
|
|
tag := podmanTest.Podman([]string{"tag", oldBB, BB})
|
|
tag.WaitWithDefaultTimeout()
|
|
Expect(tag.ExitCode()).To(BeZero())
|
|
|
|
rmi := podmanTest.Podman([]string{"rmi", oldBB})
|
|
rmi.WaitWithDefaultTimeout()
|
|
Expect(rmi.ExitCode()).To(BeZero())
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", BB})
|
|
inspect.WaitWithDefaultTimeout()
|
|
oldBBinspect := inspect.InspectImageJSON()
|
|
|
|
ctr := getCtr(withPullPolicy("always"), withImage(BB))
|
|
err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect = podmanTest.Podman([]string{"inspect", BB})
|
|
inspect.WaitWithDefaultTimeout()
|
|
newBBinspect := inspect.InspectImageJSON()
|
|
Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest)))
|
|
})
|
|
|
|
It("podman play kube with latest image should always pull", func() {
|
|
oldBB := "quay.io/libpod/busybox:1.30.1"
|
|
pull := podmanTest.Podman([]string{"pull", oldBB})
|
|
pull.WaitWithDefaultTimeout()
|
|
|
|
tag := podmanTest.Podman([]string{"tag", oldBB, BB})
|
|
tag.WaitWithDefaultTimeout()
|
|
Expect(tag.ExitCode()).To(BeZero())
|
|
|
|
rmi := podmanTest.Podman([]string{"rmi", oldBB})
|
|
rmi.WaitWithDefaultTimeout()
|
|
Expect(rmi.ExitCode()).To(BeZero())
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", BB})
|
|
inspect.WaitWithDefaultTimeout()
|
|
oldBBinspect := inspect.InspectImageJSON()
|
|
|
|
ctr := getCtr(withImage(BB))
|
|
err := generateKubeYaml("pod", getPod(withCtr(ctr)), kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect = podmanTest.Podman([]string{"inspect", BB})
|
|
inspect.WaitWithDefaultTimeout()
|
|
newBBinspect := inspect.InspectImageJSON()
|
|
Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest)))
|
|
})
|
|
|
|
It("podman play kube with image data", func() {
|
|
testyaml := `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: demo_pod
|
|
spec:
|
|
containers:
|
|
- image: demo
|
|
name: demo_kube
|
|
`
|
|
pull := podmanTest.Podman([]string{"create", "--workdir", "/etc", "--name", "newBB", "--label", "key1=value1", "alpine"})
|
|
|
|
pull.WaitWithDefaultTimeout()
|
|
Expect(pull.ExitCode()).To(BeZero())
|
|
|
|
c := podmanTest.Podman([]string{"commit", "-c", "STOPSIGNAL=51", "newBB", "demo"})
|
|
c.WaitWithDefaultTimeout()
|
|
Expect(c.ExitCode()).To(Equal(0))
|
|
|
|
conffile := filepath.Join(podmanTest.TempDir, "kube.yaml")
|
|
tempdir, err = CreateTempDirInTempDir()
|
|
Expect(err).To(BeNil())
|
|
|
|
err := ioutil.WriteFile(conffile, []byte(testyaml), 0755)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", conffile})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", "demo_pod-demo_kube"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
|
|
ctr := inspect.InspectContainerToJSON()
|
|
Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc"))
|
|
Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
|
|
Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
|
|
Expect(ctr[0].Config.StopSignal).To(Equal(uint(51)))
|
|
})
|
|
|
|
// Deployment related tests
|
|
It("podman play kube deployment 1 replica test correct command", func() {
|
|
deployment := getDeployment()
|
|
err := generateKubeYaml("deployment", deployment, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
podNames := getPodNamesInDeployment(deployment)
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[0]), "--format", "'{{ .Config.Cmd }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
// yaml's command shuold override the image's Entrypoint
|
|
correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
|
|
})
|
|
|
|
It("podman play kube deployment more than 1 replica test correct command", func() {
|
|
var i, numReplicas int32
|
|
numReplicas = 5
|
|
deployment := getDeployment(withReplicas(numReplicas))
|
|
err := generateKubeYaml("deployment", deployment, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
podNames := getPodNamesInDeployment(deployment)
|
|
correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
|
|
for i = 0; i < numReplicas; i++ {
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "'{{ .Config.Cmd }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
|
|
}
|
|
})
|
|
|
|
It("podman play kube test with network portbindings", func() {
|
|
ip := "127.0.0.100"
|
|
port := "5000"
|
|
ctr := getCtr(withHostIP(ip, port), withImage(BB))
|
|
|
|
pod := getPod(withCtr(ctr))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"port", getCtrNameInPod(pod)})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(Equal("5000/tcp -> 127.0.0.100:5000"))
|
|
})
|
|
|
|
It("podman play kube test with non-existent empty HostPath type volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
|
|
pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation)))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).NotTo(Equal(0))
|
|
})
|
|
|
|
It("podman play kube test with empty HostPath type volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
f, err := os.Create(hostPathLocation)
|
|
Expect(err).To(BeNil())
|
|
f.Close()
|
|
|
|
pod := getPod(withVolume(getHostPathVolume(`""`, hostPathLocation)))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
})
|
|
|
|
It("podman play kube test with non-existent File HostPath type volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
|
|
pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).NotTo(Equal(0))
|
|
})
|
|
|
|
It("podman play kube test with File HostPath type volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
f, err := os.Create(hostPathLocation)
|
|
Expect(err).To(BeNil())
|
|
f.Close()
|
|
|
|
pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
})
|
|
|
|
It("podman play kube test with FileOrCreate HostPath type volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
|
|
pod := getPod(withVolume(getHostPathVolume("FileOrCreate", hostPathLocation)))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
// the file should have been created
|
|
_, err = os.Stat(hostPathLocation)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
It("podman play kube test with DirectoryOrCreate HostPath type volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
|
|
pod := getPod(withVolume(getHostPathVolume("DirectoryOrCreate", hostPathLocation)))
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
// the file should have been created
|
|
st, err := os.Stat(hostPathLocation)
|
|
Expect(err).To(BeNil())
|
|
Expect(st.Mode().IsDir()).To(Equal(true))
|
|
})
|
|
|
|
It("podman play kube test with Socket HostPath type volume should fail if not socket", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
f, err := os.Create(hostPathLocation)
|
|
Expect(err).To(BeNil())
|
|
f.Close()
|
|
|
|
pod := getPod(withVolume(getHostPathVolume("Socket", hostPathLocation)))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).NotTo(Equal(0))
|
|
})
|
|
|
|
It("podman play kube test with read only HostPath volume", func() {
|
|
hostPathLocation := filepath.Join(tempdir, "file")
|
|
f, err := os.Create(hostPathLocation)
|
|
Expect(err).To(BeNil())
|
|
f.Close()
|
|
|
|
ctr := getCtr(withVolumeMount(hostPathLocation, true), withImage(BB))
|
|
pod := getPod(withVolume(getHostPathVolume("File", hostPathLocation)), withCtr(ctr))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{.HostConfig.Binds}}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
|
|
correct := fmt.Sprintf("%s:%s:%s", hostPathLocation, hostPathLocation, "ro")
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(correct))
|
|
})
|
|
|
|
It("podman play kube test with PersistentVolumeClaim volume", func() {
|
|
volumeName := "namedVolume"
|
|
|
|
ctr := getCtr(withVolumeMount("/test", false), withImage(BB))
|
|
pod := getPod(withVolume(getPersistentVolumeClaimVolume(volumeName)), withCtr(ctr))
|
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
|
|
correct := fmt.Sprintf("volume:%s", volumeName)
|
|
Expect(inspect.OutputToString()).To(Equal(correct))
|
|
})
|
|
|
|
It("podman play kube applies labels to pods", func() {
|
|
var numReplicas int32 = 5
|
|
expectedLabelKey := "key1"
|
|
expectedLabelValue := "value1"
|
|
deployment := getDeployment(
|
|
withReplicas(numReplicas),
|
|
withPod(getPod(withLabel(expectedLabelKey, expectedLabelValue))),
|
|
)
|
|
err := generateKubeYaml("deployment", deployment, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
correctLabels := expectedLabelKey + ":" + expectedLabelValue
|
|
for _, pod := range getPodNamesInDeployment(deployment) {
|
|
inspect := podmanTest.Podman([]string{"pod", "inspect", pod.Name, "--format", "'{{ .Labels }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(correctLabels))
|
|
}
|
|
})
|
|
|
|
It("podman play kube allows setting resource limits", func() {
|
|
SkipIfContainerized("Resource limits require a running systemd")
|
|
SkipIfRootlessCgroupsV1("Limits require root or cgroups v2")
|
|
SkipIfUnprivilegedCPULimits()
|
|
podmanTest.CgroupManager = "systemd"
|
|
|
|
var (
|
|
numReplicas int32 = 3
|
|
expectedCpuRequest string = "100m"
|
|
expectedCpuLimit string = "200m"
|
|
expectedMemoryRequest string = "10000000"
|
|
expectedMemoryLimit string = "20000000"
|
|
)
|
|
|
|
expectedCpuQuota := milliCPUToQuota(expectedCpuLimit)
|
|
|
|
deployment := getDeployment(
|
|
withReplicas(numReplicas),
|
|
withPod(getPod(withCtr(getCtr(
|
|
withCpuRequest(expectedCpuRequest),
|
|
withCpuLimit(expectedCpuLimit),
|
|
withMemoryRequest(expectedMemoryRequest),
|
|
withMemoryLimit(expectedMemoryLimit),
|
|
)))))
|
|
err := generateKubeYaml("deployment", deployment, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
for _, pod := range getPodNamesInDeployment(deployment) {
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", `
|
|
CpuPeriod: {{ .HostConfig.CpuPeriod }}
|
|
CpuQuota: {{ .HostConfig.CpuQuota }}
|
|
Memory: {{ .HostConfig.Memory }}
|
|
MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring(fmt.Sprintf("%s: %d", "CpuQuota", expectedCpuQuota)))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring("MemoryReservation: " + expectedMemoryRequest))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring("Memory: " + expectedMemoryLimit))
|
|
}
|
|
})
|
|
|
|
It("podman play kube reports invalid image name", func() {
|
|
invalidImageName := "./myimage"
|
|
|
|
pod := getPod(
|
|
withCtr(
|
|
getCtr(
|
|
withImage(invalidImageName),
|
|
),
|
|
),
|
|
)
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(125))
|
|
Expect(kube.ErrorToString()).To(ContainSubstring(invalidImageName))
|
|
})
|
|
|
|
It("podman play kube applies log driver to containers", func() {
|
|
Skip("need to verify images have correct packages for journald")
|
|
pod := getPod()
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", "--log-driver", "journald", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .HostConfig.LogConfig.Type }}'"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(ContainSubstring("journald"))
|
|
})
|
|
|
|
It("podman play kube test only creating the containers", func() {
|
|
pod := getPod()
|
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
|
Expect(err).To(BeNil())
|
|
|
|
kube := podmanTest.Podman([]string{"play", "kube", "--start=false", kubeYaml})
|
|
kube.WaitWithDefaultTimeout()
|
|
Expect(kube.ExitCode()).To(Equal(0))
|
|
|
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ .State.Running }}"})
|
|
inspect.WaitWithDefaultTimeout()
|
|
Expect(inspect.ExitCode()).To(Equal(0))
|
|
Expect(inspect.OutputToString()).To(Equal("false"))
|
|
})
|
|
})
|