• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubevirt / kubevirt / ebc45ffd-4c39-4410-8928-259b6e678e85

24 Jan 2025 09:15AM UTC coverage: 71.556% (+0.02%) from 71.536%
ebc45ffd-4c39-4410-8928-259b6e678e85

push

prow

web-flow
Merge pull request #13769 from xpivarc/required-scc

Provide openshift.io/required-scc

15 of 20 new or added lines in 2 files covered. (75.0%)

151 existing lines in 5 files now uncovered.

61664 of 86176 relevant lines covered (71.56%)

0.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.67
/pkg/virt-controller/services/rendercontainer.go
1
package services
2

3
import (
4
        "strconv"
5
        "strings"
6

7
        k8sv1 "k8s.io/api/core/v1"
8

9
        "kubevirt.io/kubevirt/pkg/pointer"
10

11
        v1 "kubevirt.io/api/core/v1"
12

13
        "kubevirt.io/kubevirt/pkg/util"
14
        "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
15
)
16

17
const (
18
        cacheHomeEnvVarName  = "XDG_CACHE_HOME"
19
        configHomeEnvVarName = "XDG_CONFIG_HOME"
20
        runtimeDirEnvVarName = "XDG_RUNTIME_DIR"
21
)
22

23
type ContainerSpecRenderer struct {
24
        imgPullPolicy     k8sv1.PullPolicy
25
        isPrivileged      bool
26
        launcherImg       string
27
        name              string
28
        userID            int64
29
        volumeDevices     []k8sv1.VolumeDevice
30
        volumeMounts      []k8sv1.VolumeMount
31
        sharedFilesystems []string
32
        resources         k8sv1.ResourceRequirements
33
        liveninessProbe   *k8sv1.Probe
34
        readinessProbe    *k8sv1.Probe
35
        ports             []k8sv1.ContainerPort
36
        capabilities      *k8sv1.Capabilities
37
        args              []string
38
}
39

40
type Option func(*ContainerSpecRenderer)
41

42
func NewContainerSpecRenderer(containerName string, launcherImg string, imgPullPolicy k8sv1.PullPolicy, opts ...Option) *ContainerSpecRenderer {
1✔
43
        computeContainerSpec := &ContainerSpecRenderer{
1✔
44
                imgPullPolicy: imgPullPolicy,
1✔
45
                launcherImg:   launcherImg,
1✔
46
                name:          containerName,
1✔
47
        }
1✔
48
        for _, opt := range opts {
2✔
49
                opt(computeContainerSpec)
1✔
50
        }
1✔
51
        return computeContainerSpec
1✔
52
}
53

54
func (csr *ContainerSpecRenderer) Render(cmd []string) k8sv1.Container {
1✔
55
        return k8sv1.Container{
1✔
56
                Name:            csr.name,
1✔
57
                Image:           csr.launcherImg,
1✔
58
                ImagePullPolicy: csr.imgPullPolicy,
1✔
59
                SecurityContext: securityContext(csr.userID, csr.isPrivileged, csr.capabilities),
1✔
60
                Command:         cmd,
1✔
61
                VolumeDevices:   csr.volumeDevices,
1✔
62
                VolumeMounts:    csr.volumeMounts,
1✔
63
                Resources:       csr.resources,
1✔
64
                Ports:           csr.ports,
1✔
65
                Env:             csr.envVars(),
1✔
66
                LivenessProbe:   csr.liveninessProbe,
1✔
67
                ReadinessProbe:  csr.readinessProbe,
1✔
68
                Args:            csr.args,
1✔
69
        }
1✔
70
}
1✔
71

72
func (csr *ContainerSpecRenderer) envVars() []k8sv1.EnvVar {
1✔
73
        var env []k8sv1.EnvVar
1✔
74

1✔
75
        if csr.userID != 0 {
2✔
76
                env = append(env, xdgEnvironmentVariables()...)
1✔
77
        }
1✔
78

79
        if len(csr.sharedFilesystems) != 0 {
2✔
80
                env = append(env, k8sv1.EnvVar{
1✔
81
                        Name:  ENV_VAR_SHARED_FILESYSTEM_PATHS,
1✔
82
                        Value: strings.Join(csr.sharedFilesystems, ":"),
1✔
83
                })
1✔
84
        }
1✔
85

86
        return env
1✔
87
}
88

89
func WithNonRoot(userID int64) Option {
1✔
90
        return func(renderer *ContainerSpecRenderer) {
2✔
91
                renderer.userID = userID
1✔
92
        }
1✔
93
}
94

95
func WithPrivileged() Option {
1✔
96
        return func(renderer *ContainerSpecRenderer) {
2✔
97
                renderer.isPrivileged = true
1✔
98
        }
1✔
99
}
100

101
func WithCapabilities(vmi *v1.VirtualMachineInstance) Option {
1✔
102
        return func(renderer *ContainerSpecRenderer) {
2✔
103
                if renderer.capabilities == nil {
2✔
104
                        renderer.capabilities = &k8sv1.Capabilities{
1✔
105
                                Add: requiredCapabilities(vmi),
1✔
106
                        }
1✔
107
                } else {
1✔
UNCOV
108
                        renderer.capabilities.Add = requiredCapabilities(vmi)
×
UNCOV
109
                }
×
110
        }
111
}
112

113
func WithDropALLCapabilities() Option {
1✔
114
        return func(renderer *ContainerSpecRenderer) {
2✔
115
                if renderer.capabilities == nil {
2✔
116
                        renderer.capabilities = &k8sv1.Capabilities{
1✔
117
                                Drop: []k8sv1.Capability{"ALL"},
1✔
118
                        }
1✔
119
                } else {
2✔
120
                        renderer.capabilities.Drop = []k8sv1.Capability{"ALL"}
1✔
121
                }
1✔
122
        }
123
}
124

125
func WithNoCapabilities() Option {
1✔
126
        return func(renderer *ContainerSpecRenderer) {
2✔
127
                renderer.capabilities = &k8sv1.Capabilities{
1✔
128
                        Drop: []k8sv1.Capability{"ALL"},
1✔
129
                }
1✔
130
        }
1✔
131
}
132

133
func WithVolumeDevices(devices ...k8sv1.VolumeDevice) Option {
1✔
134
        return func(renderer *ContainerSpecRenderer) {
2✔
135
                renderer.volumeDevices = devices
1✔
136
        }
1✔
137
}
138

139
func WithVolumeMounts(mounts ...k8sv1.VolumeMount) Option {
1✔
140
        return func(renderer *ContainerSpecRenderer) {
2✔
141
                renderer.volumeMounts = mounts
1✔
142
        }
1✔
143
}
144

145
func WithSharedFilesystems(paths ...string) Option {
1✔
146
        return func(renderer *ContainerSpecRenderer) {
2✔
147
                renderer.sharedFilesystems = paths
1✔
148
        }
1✔
149
}
150

151
func WithResourceRequirements(resources k8sv1.ResourceRequirements) Option {
1✔
152
        return func(renderer *ContainerSpecRenderer) {
2✔
153
                renderer.resources = resources
1✔
154
        }
1✔
155
}
156

157
func WithPorts(vmi *v1.VirtualMachineInstance) Option {
1✔
158
        return func(renderer *ContainerSpecRenderer) {
2✔
159
                renderer.ports = containerPortsFromVMI(vmi)
1✔
160
        }
1✔
161
}
162

163
func WithArgs(args []string) Option {
1✔
164
        return func(renderer *ContainerSpecRenderer) {
2✔
165
                renderer.args = args
1✔
166
        }
1✔
167
}
168

169
func WithLivelinessProbe(vmi *v1.VirtualMachineInstance) Option {
1✔
170
        return func(renderer *ContainerSpecRenderer) {
2✔
171
                v1.SetDefaults_Probe(vmi.Spec.LivenessProbe)
1✔
172
                renderer.liveninessProbe = copyProbe(vmi.Spec.LivenessProbe)
1✔
173
                updateLivenessProbe(vmi, renderer.liveninessProbe)
1✔
174
        }
1✔
175
}
176

177
func WithReadinessProbe(vmi *v1.VirtualMachineInstance) Option {
1✔
178
        return func(renderer *ContainerSpecRenderer) {
2✔
179
                v1.SetDefaults_Probe(vmi.Spec.ReadinessProbe)
1✔
180
                renderer.readinessProbe = copyProbe(vmi.Spec.ReadinessProbe)
1✔
181
                updateReadinessProbe(vmi, renderer.readinessProbe)
1✔
182
        }
1✔
183
}
184

185
func xdgEnvironmentVariables() []k8sv1.EnvVar {
1✔
186
        const varRun = "/var/run"
1✔
187
        return []k8sv1.EnvVar{
1✔
188
                {
1✔
189
                        Name:  cacheHomeEnvVarName,
1✔
190
                        Value: util.VirtPrivateDir,
1✔
191
                },
1✔
192
                {
1✔
193
                        Name:  configHomeEnvVarName,
1✔
194
                        Value: util.VirtPrivateDir,
1✔
195
                },
1✔
196
                {
1✔
197
                        Name:  runtimeDirEnvVarName,
1✔
198
                        Value: varRun,
1✔
199
                },
1✔
200
        }
1✔
201
}
1✔
202

203
func securityContext(userId int64, privileged bool, requiredCapabilities *k8sv1.Capabilities) *k8sv1.SecurityContext {
1✔
204
        isNonRoot := userId != 0
1✔
205
        context := &k8sv1.SecurityContext{
1✔
206
                RunAsUser:    &userId,
1✔
207
                RunAsNonRoot: &isNonRoot,
1✔
208
                Privileged:   &privileged,
1✔
209
                Capabilities: requiredCapabilities,
1✔
210
        }
1✔
211

1✔
212
        if isNonRoot {
2✔
213
                context.RunAsGroup = &userId
1✔
214
                context.AllowPrivilegeEscalation = pointer.P(false)
1✔
215
        }
1✔
216

217
        return context
1✔
218
}
219

220
func containerPortsFromVMI(vmi *v1.VirtualMachineInstance) []k8sv1.ContainerPort {
1✔
221
        var ports []k8sv1.ContainerPort
1✔
222

1✔
223
        for _, iface := range vmi.Spec.Domain.Devices.Interfaces {
2✔
224
                if iface.Ports != nil {
2✔
225
                        for _, port := range iface.Ports {
2✔
226
                                if port.Protocol == "" {
2✔
227
                                        port.Protocol = "TCP"
1✔
228
                                }
1✔
229

230
                                ports = append(ports, k8sv1.ContainerPort{Protocol: k8sv1.Protocol(port.Protocol), Name: port.Name, ContainerPort: port.Port})
1✔
231
                        }
232
                }
233
        }
234

235
        return ports
1✔
236
}
237

238
func updateReadinessProbe(vmi *v1.VirtualMachineInstance, computeProbe *k8sv1.Probe) {
1✔
239
        if vmi.Spec.ReadinessProbe.GuestAgentPing != nil {
1✔
UNCOV
240
                wrapGuestAgentPingWithVirtProbe(vmi, computeProbe)
×
UNCOV
241
                computeProbe.InitialDelaySeconds = computeProbe.InitialDelaySeconds + LibvirtStartupDelay
×
UNCOV
242
                return
×
UNCOV
243
        }
×
244
        wrapExecProbeWithVirtProbe(vmi, computeProbe)
1✔
245
        computeProbe.InitialDelaySeconds = computeProbe.InitialDelaySeconds + LibvirtStartupDelay
1✔
246
}
247

248
func updateLivenessProbe(vmi *v1.VirtualMachineInstance, computeProbe *k8sv1.Probe) {
1✔
249
        if vmi.Spec.LivenessProbe.GuestAgentPing != nil {
1✔
250
                wrapGuestAgentPingWithVirtProbe(vmi, computeProbe)
×
251
                computeProbe.InitialDelaySeconds = computeProbe.InitialDelaySeconds + LibvirtStartupDelay
×
252
                return
×
253
        }
×
254
        wrapExecProbeWithVirtProbe(vmi, computeProbe)
1✔
255
        computeProbe.InitialDelaySeconds = computeProbe.InitialDelaySeconds + LibvirtStartupDelay
1✔
256
}
257

258
func wrapExecProbeWithVirtProbe(vmi *v1.VirtualMachineInstance, probe *k8sv1.Probe) {
1✔
259
        if probe == nil || probe.ProbeHandler.Exec == nil {
2✔
260
                return
1✔
261
        }
1✔
262

UNCOV
263
        originalCommand := probe.ProbeHandler.Exec.Command
×
UNCOV
264
        if len(originalCommand) < 1 {
×
UNCOV
265
                return
×
UNCOV
266
        }
×
267

UNCOV
268
        wrappedCommand := []string{
×
UNCOV
269
                "virt-probe",
×
UNCOV
270
                "--domainName", api.VMINamespaceKeyFunc(vmi),
×
UNCOV
271
                "--timeoutSeconds", strconv.FormatInt(int64(probe.TimeoutSeconds), 10),
×
UNCOV
272
                "--command", originalCommand[0],
×
UNCOV
273
                "--",
×
UNCOV
274
        }
×
UNCOV
275
        wrappedCommand = append(wrappedCommand, originalCommand[1:]...)
×
UNCOV
276

×
UNCOV
277
        probe.ProbeHandler.Exec.Command = wrappedCommand
×
UNCOV
278
        // we add 1s to the pod probe to compensate for the additional steps in probing
×
UNCOV
279
        probe.TimeoutSeconds += 1
×
280
}
281

282
func requiredCapabilities(vmi *v1.VirtualMachineInstance) []k8sv1.Capability {
1✔
283
        // These capabilies are always required because we set them on virt-launcher binary
1✔
284
        capabilities := []k8sv1.Capability{CAP_NET_BIND_SERVICE}
1✔
285

1✔
286
        if !util.IsNonRootVMI(vmi) {
2✔
287
                // add a CAP_SYS_NICE capability to allow setting cpu affinity
1✔
288
                capabilities = append(capabilities, CAP_SYS_NICE)
1✔
289
        }
1✔
290

291
        return capabilities
1✔
292
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc