mirror of
https://github.com/containers/podman.git
synced 2025-06-23 02:18:13 +08:00
Merge pull request #19371 from danishprakash/daemonset-support
kube: add DaemonSet support
This commit is contained in:
@ -246,6 +246,22 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
|
|||||||
}
|
}
|
||||||
notifyProxies = append(notifyProxies, proxies...)
|
notifyProxies = append(notifyProxies, proxies...)
|
||||||
|
|
||||||
|
report.Pods = append(report.Pods, r.Pods...)
|
||||||
|
validKinds++
|
||||||
|
ranContainers = true
|
||||||
|
case "DaemonSet":
|
||||||
|
var daemonSetYAML v1apps.DaemonSet
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal(document, &daemonSetYAML); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to read YAML as Kube DaemonSet: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, proxies, err := ic.playKubeDaemonSet(ctx, &daemonSetYAML, options, &ipIndex, configMaps, serviceContainer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
notifyProxies = append(notifyProxies, proxies...)
|
||||||
|
|
||||||
report.Pods = append(report.Pods, r.Pods...)
|
report.Pods = append(report.Pods, r.Pods...)
|
||||||
validKinds++
|
validKinds++
|
||||||
ranContainers = true
|
ranContainers = true
|
||||||
@ -366,6 +382,29 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
|
|||||||
return report, nil
|
return report, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ic *ContainerEngine) playKubeDaemonSet(ctx context.Context, daemonSetYAML *v1apps.DaemonSet, options entities.PlayKubeOptions, ipIndex *int, configMaps []v1.ConfigMap, serviceContainer *libpod.Container) (*entities.PlayKubeReport, []*notifyproxy.NotifyProxy, error) {
|
||||||
|
var (
|
||||||
|
daemonSetName string
|
||||||
|
podSpec v1.PodTemplateSpec
|
||||||
|
report entities.PlayKubeReport
|
||||||
|
)
|
||||||
|
|
||||||
|
daemonSetName = daemonSetYAML.ObjectMeta.Name
|
||||||
|
if daemonSetName == "" {
|
||||||
|
return nil, nil, errors.New("daemonSet does not have a name")
|
||||||
|
}
|
||||||
|
podSpec = daemonSetYAML.Spec.Template
|
||||||
|
|
||||||
|
podName := fmt.Sprintf("%s-pod", daemonSetName)
|
||||||
|
podReport, proxies, err := ic.playKubePod(ctx, podName, &podSpec, options, ipIndex, daemonSetYAML.Annotations, configMaps, serviceContainer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("encountered while bringing up pod %s: %w", podName, err)
|
||||||
|
}
|
||||||
|
report.Pods = podReport.Pods
|
||||||
|
|
||||||
|
return &report, proxies, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int, configMaps []v1.ConfigMap, serviceContainer *libpod.Container) (*entities.PlayKubeReport, []*notifyproxy.NotifyProxy, error) {
|
func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions, ipIndex *int, configMaps []v1.ConfigMap, serviceContainer *libpod.Container) (*entities.PlayKubeReport, []*notifyproxy.NotifyProxy, error) {
|
||||||
var (
|
var (
|
||||||
deploymentName string
|
deploymentName string
|
||||||
@ -1249,7 +1288,7 @@ func sortKubeKinds(documentList [][]byte) ([][]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch kind {
|
switch kind {
|
||||||
case "Pod", "Deployment":
|
case "Pod", "Deployment", "DaemonSet":
|
||||||
sortedDocumentList = append(sortedDocumentList, document)
|
sortedDocumentList = append(sortedDocumentList, document)
|
||||||
default:
|
default:
|
||||||
sortedDocumentList = append([][]byte{document}, sortedDocumentList...)
|
sortedDocumentList = append([][]byte{document}, sortedDocumentList...)
|
||||||
@ -1354,6 +1393,15 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, opt
|
|||||||
volumeNames = append(volumeNames, vs.Secret.SecretName)
|
volumeNames = append(volumeNames, vs.Secret.SecretName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "DaemonSet":
|
||||||
|
var daemonSetYAML v1apps.DaemonSet
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal(document, &daemonSetYAML); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to read YAML as Kube DaemonSet: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
podName := fmt.Sprintf("%s-pod", daemonSetYAML.Name)
|
||||||
|
podNames = append(podNames, podName)
|
||||||
case "Deployment":
|
case "Deployment":
|
||||||
var deploymentYAML v1apps.Deployment
|
var deploymentYAML v1apps.Deployment
|
||||||
|
|
||||||
|
@ -723,6 +723,159 @@ spec:
|
|||||||
status: {}
|
status: {}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var daemonSetYamlTemplate = `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: DaemonSet
|
||||||
|
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:
|
||||||
|
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 }}
|
||||||
|
hostNetwork: {{ .HostNetwork }}
|
||||||
|
containers:
|
||||||
|
{{ with .Ctrs }}
|
||||||
|
{{ range . }}
|
||||||
|
- command:
|
||||||
|
{{ range .Cmd }}
|
||||||
|
- {{.}}
|
||||||
|
{{ end }}
|
||||||
|
args:
|
||||||
|
{{ range .Arg }}
|
||||||
|
- {{.}}
|
||||||
|
{{ end }}
|
||||||
|
env:
|
||||||
|
- name: HOSTNAME
|
||||||
|
{{ range .Env }}
|
||||||
|
- name: {{ .Name }}
|
||||||
|
{{ if (eq .ValueFrom "configmap") }}
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ .RefName }}
|
||||||
|
key: {{ .RefKey }}
|
||||||
|
optional: {{ .Optional }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if (eq .ValueFrom "secret") }}
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ .RefName }}
|
||||||
|
key: {{ .RefKey }}
|
||||||
|
optional: {{ .Optional }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if (eq .ValueFrom "") }}
|
||||||
|
value: {{ .Value }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ with .EnvFrom}}
|
||||||
|
envFrom:
|
||||||
|
{{ range . }}
|
||||||
|
{{ if (eq .From "configmap") }}
|
||||||
|
- configMapRef:
|
||||||
|
name: {{ .Name }}
|
||||||
|
optional: {{ .Optional }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if (eq .From "secret") }}
|
||||||
|
- secretRef:
|
||||||
|
name: {{ .Name }}
|
||||||
|
optional: {{ .Optional }}
|
||||||
|
{{ 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
|
||||||
|
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 }}
|
||||||
|
{{ end }}
|
||||||
|
`
|
||||||
var deploymentYamlTemplate = `
|
var deploymentYamlTemplate = `
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@ -1044,6 +1197,7 @@ var (
|
|||||||
defaultCtrImage = ALPINE
|
defaultCtrImage = ALPINE
|
||||||
defaultPodName = "testPod"
|
defaultPodName = "testPod"
|
||||||
defaultVolName = "testVol"
|
defaultVolName = "testVol"
|
||||||
|
defaultDaemonSetName = "testDaemonSet"
|
||||||
defaultDeploymentName = "testDeployment"
|
defaultDeploymentName = "testDeployment"
|
||||||
defaultConfigMapName = "testConfigMap"
|
defaultConfigMapName = "testConfigMap"
|
||||||
defaultSecretName = "testSecret"
|
defaultSecretName = "testSecret"
|
||||||
@ -1065,6 +1219,8 @@ func getKubeYaml(kind string, object interface{}) (string, error) {
|
|||||||
yamlTemplate = configMapYamlTemplate
|
yamlTemplate = configMapYamlTemplate
|
||||||
case "pod":
|
case "pod":
|
||||||
yamlTemplate = podYamlTemplate
|
yamlTemplate = podYamlTemplate
|
||||||
|
case "daemonset":
|
||||||
|
yamlTemplate = daemonSetYamlTemplate
|
||||||
case "deployment":
|
case "deployment":
|
||||||
yamlTemplate = deploymentYamlTemplate
|
yamlTemplate = deploymentYamlTemplate
|
||||||
case "persistentVolumeClaim":
|
case "persistentVolumeClaim":
|
||||||
@ -1356,6 +1512,29 @@ func withHostUsers(val bool) podOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deployment describes the options a kube yaml can be configured at deployment level
|
// Deployment describes the options a kube yaml can be configured at deployment level
|
||||||
|
type DaemonSet struct {
|
||||||
|
Name string
|
||||||
|
Labels map[string]string
|
||||||
|
Annotations map[string]string
|
||||||
|
PodTemplate *Pod
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDaemonSet(options ...daemonSetOption) *DaemonSet {
|
||||||
|
d := DaemonSet{
|
||||||
|
Name: defaultDaemonSetName,
|
||||||
|
Labels: make(map[string]string),
|
||||||
|
Annotations: make(map[string]string),
|
||||||
|
PodTemplate: getPod(),
|
||||||
|
}
|
||||||
|
for _, option := range options {
|
||||||
|
option(&d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &d
|
||||||
|
}
|
||||||
|
|
||||||
|
type daemonSetOption func(*DaemonSet)
|
||||||
|
|
||||||
type Deployment struct {
|
type Deployment struct {
|
||||||
Name string
|
Name string
|
||||||
Replicas int32
|
Replicas int32
|
||||||
@ -1399,6 +1578,16 @@ func withReplicas(replicas int32) deploymentOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPodNameInDeployment returns the Pod object
|
||||||
|
// with just its name set, so that it can be passed around
|
||||||
|
// and into getCtrNameInPod for ease of testing
|
||||||
|
func getPodNameInDaemonSet(d *DaemonSet) Pod {
|
||||||
|
p := Pod{}
|
||||||
|
p.Name = fmt.Sprintf("%s-pod", d.Name)
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
// getPodNameInDeployment returns the Pod object
|
// getPodNameInDeployment returns the Pod object
|
||||||
// with just its name set, so that it can be passed around
|
// with just its name set, so that it can be passed around
|
||||||
// and into getCtrNameInPod for ease of testing
|
// and into getCtrNameInPod for ease of testing
|
||||||
@ -2951,6 +3140,23 @@ spec:
|
|||||||
Expect(ctr[0].Config).To(HaveField("StopSignal", uint(51)))
|
Expect(ctr[0].Config).To(HaveField("StopSignal", uint(51)))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman play kube daemonset sanity", func() {
|
||||||
|
daemonset := getDaemonSet()
|
||||||
|
err := generateKubeYaml("daemonset", daemonset, kubeYaml)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
podName := getPodNameInDaemonSet(daemonset)
|
||||||
|
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podName), "--format", "'{{ .Config.Entrypoint }}'"})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
// yaml's command should override the image's Entrypoint
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " ")))
|
||||||
|
})
|
||||||
|
|
||||||
// Deployment related tests
|
// Deployment related tests
|
||||||
It("podman play kube deployment 1 replica test correct command", func() {
|
It("podman play kube deployment 1 replica test correct command", func() {
|
||||||
deployment := getDeployment()
|
deployment := getDeployment()
|
||||||
|
Reference in New Issue
Block a user