Merge pull request #19371 from danishprakash/daemonset-support

kube: add DaemonSet support
This commit is contained in:
OpenShift Merge Robot
2023-08-08 17:05:09 -04:00
committed by GitHub
2 changed files with 255 additions and 1 deletions

View File

@ -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

View File

@ -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()