Skip to content

Commit e7fd072

Browse files
authored
[Feature] Add Core fields to the Scheduler Container Spec (#1616)
1 parent 6157684 commit e7fd072

14 files changed

+908
-18
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Change Log
22

33
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
4+
- (Feature) Add Core fields to the Scheduler Container Spec
45

56
## [1.2.39](https://github.com/arangodb/kube-arangodb/tree/1.2.39) (2024-03-11)
67
- (Feature) Extract Scheduler API

docs/api/ArangoMLExtension.V1Alpha1.md

+440
Large diffs are not rendered by default.

docs/api/ArangoMLStorage.V1Alpha1.md

+44
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,40 @@ Default Value: `/`
104104

105105
***
106106

107+
### .spec.mode.sidecar.args
108+
109+
Type: `array` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.39/pkg/apis/scheduler/v1alpha1/container/resources/core.go#L50)</sup>
110+
111+
Arguments to the entrypoint.
112+
The container image's CMD is used if this is not provided.
113+
Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
114+
cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
115+
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
116+
produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
117+
of whether the variable exists or not. Cannot be updated.
118+
119+
Links:
120+
* [Kubernetes Docs](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell)
121+
122+
***
123+
124+
### .spec.mode.sidecar.command
125+
126+
Type: `array` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.39/pkg/apis/scheduler/v1alpha1/container/resources/core.go#L40)</sup>
127+
128+
Entrypoint array. Not executed within a shell.
129+
The container image's ENTRYPOINT is used if this is not provided.
130+
Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
131+
cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
132+
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
133+
produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
134+
of whether the variable exists or not. Cannot be updated.
135+
136+
Links:
137+
* [Kubernetes Docs](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell)
138+
139+
***
140+
107141
### .spec.mode.sidecar.controllerListenPort
108142

109143
Type: `integer` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.39/pkg/apis/ml/v1alpha1/storage_spec_mode_sidecar.go#L36)</sup>
@@ -258,6 +292,16 @@ Type: `[]core.VolumeMount` <sup>[\[ref\]](https://github.com/arangodb/kube-arang
258292

259293
VolumeMounts keeps list of pod volumes to mount into the container's filesystem.
260294

295+
***
296+
297+
### .spec.mode.sidecar.workingDir
298+
299+
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.39/pkg/apis/scheduler/v1alpha1/container/resources/core.go#L55)</sup>
300+
301+
Container's working directory.
302+
If not specified, the container runtime's default will be used, which
303+
might be configured in the container image.
304+
261305
## Status
262306

263307
### .status.conditions

pkg/apis/scheduler/v1alpha1/container/definition.go

+14
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ func (c Containers) Validate() error {
104104
var _ interfaces.Container[Container] = &Container{}
105105

106106
type Container struct {
107+
// Core keeps the core settings for Container
108+
*schedulerContainerResourcesApi.Core `json:",inline"`
109+
107110
// Security keeps the security settings for Container
108111
*schedulerContainerResourcesApi.Security `json:",inline"`
109112

@@ -135,6 +138,7 @@ func (c *Container) Apply(template *core.PodTemplateSpec, container *core.Contai
135138
}
136139

137140
return shared.WithErrors(
141+
c.Core.Apply(template, container),
138142
c.Security.Apply(template, container),
139143
c.Environments.Apply(template, container),
140144
c.Image.Apply(template, container),
@@ -146,6 +150,14 @@ func (c *Container) Apply(template *core.PodTemplateSpec, container *core.Contai
146150
)
147151
}
148152

153+
func (c *Container) GetCore() *schedulerContainerResourcesApi.Core {
154+
if c == nil || c.Core == nil {
155+
return nil
156+
}
157+
158+
return c.Core
159+
}
160+
149161
func (c *Container) GetImage() *schedulerContainerResourcesApi.Image {
150162
if c == nil || c.Image == nil {
151163
return nil
@@ -224,6 +236,7 @@ func (c *Container) With(other *Container) *Container {
224236
}
225237

226238
return &Container{
239+
Core: c.Core.With(other.Core),
227240
Security: c.Security.With(other.Security),
228241
Environments: c.Environments.With(other.Environments),
229242
Image: c.Image.With(other.Image),
@@ -241,6 +254,7 @@ func (c *Container) Validate() error {
241254
}
242255

243256
return shared.WithErrors(
257+
shared.PrefixResourceErrors("core", c.Core.Validate()),
244258
shared.PrefixResourceErrors("containerSecurity", c.Security.Validate()),
245259
shared.PrefixResourceErrors("containerEnvironments", c.Environments.Validate()),
246260
shared.PrefixResourceErrors("containerResources", c.Image.Validate()),

pkg/apis/scheduler/v1alpha1/container/definition_container_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ func Test_Container(t *testing.T) {
9090
require.Nil(t, spec.Image)
9191
require.Nil(t, spec.Security)
9292
require.Nil(t, spec.Environments)
93+
require.Nil(t, spec.VolumeMounts)
94+
require.Nil(t, spec.Core)
9395

9496
require.Len(t, container.Env, 0)
9597
})
@@ -100,12 +102,17 @@ func Test_Container(t *testing.T) {
100102
require.Nil(t, spec.Image)
101103
require.Nil(t, spec.Security)
102104
require.Nil(t, spec.Environments)
105+
require.Nil(t, spec.VolumeMounts)
106+
require.Nil(t, spec.Core)
103107

104108
require.Len(t, container.Env, 0)
105109
})
106110
})
107111
t.Run("With fields", func(t *testing.T) {
108112
applyContainer(t, &core.PodTemplateSpec{}, &core.Container{}, &Container{
113+
Core: &schedulerContainerResourcesApi.Core{
114+
Args: []string{"A"},
115+
},
109116
Security: &schedulerContainerResourcesApi.Security{
110117
SecurityContext: &core.SecurityContext{
111118
RunAsUser: util.NewType[int64](50),
@@ -171,6 +178,12 @@ func Test_Container(t *testing.T) {
171178
},
172179
})(func(t *testing.T, pod *core.PodTemplateSpec, container *core.Container, spec *Container) {
173180
// Spec
181+
require.NotNil(t, spec.Core)
182+
require.NotNil(t, spec.Core.Args)
183+
require.Contains(t, spec.Core.Args, "A")
184+
require.Empty(t, spec.Core.Command)
185+
require.Empty(t, spec.Core.WorkingDir)
186+
174187
require.NotNil(t, spec.Resources)
175188
require.NotNil(t, spec.Resources.Resources)
176189
require.Contains(t, spec.Resources.Resources.Limits, core.ResourceCPU)
@@ -225,6 +238,9 @@ func Test_Container_YAML(t *testing.T) {
225238
securityContext:
226239
runAsUser: 50
227240
241+
args:
242+
- A
243+
228244
env:
229245
- name: key1
230246
value: value1
@@ -264,6 +280,12 @@ securityContext:
264280
runAsUser: 10
265281
`)(func(t *testing.T, pod *core.PodTemplateSpec, container *core.Container, spec *Container) {
266282
// Spec
283+
require.NotNil(t, spec.Core)
284+
require.NotNil(t, spec.Core.Args)
285+
require.Contains(t, spec.Core.Args, "A")
286+
require.Empty(t, spec.Core.Command)
287+
require.Empty(t, spec.Core.WorkingDir)
288+
267289
require.NotNil(t, spec.Resources)
268290
require.NotNil(t, spec.Resources.Resources)
269291
require.Contains(t, spec.Resources.Resources.Limits, core.ResourceCPU)

pkg/apis/scheduler/v1alpha1/container/generic.go

+28-14
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,20 @@ var _ interfaces.Pod[Generic] = &Generic{}
3333
type Generic struct {
3434
// Environments keeps the environment variables for Container
3535
*schedulerContainerResourcesApi.Environments `json:",inline"`
36+
37+
// VolumeMounts define volume mounts assigned to the Container
38+
*schedulerContainerResourcesApi.VolumeMounts `json:",inline"`
3639
}
3740

38-
func (c *Generic) Apply(template *core.PodTemplateSpec) error {
39-
if c == nil {
41+
func (g *Generic) Apply(template *core.PodTemplateSpec) error {
42+
if g == nil {
4043
return nil
4144
}
4245

4346
for id := range template.Spec.Containers {
4447
if err := shared.WithErrors(
45-
c.Environments.Apply(template, &template.Spec.Containers[id]),
48+
g.Environments.Apply(template, &template.Spec.Containers[id]),
49+
g.VolumeMounts.Apply(template, &template.Spec.Containers[id]),
4650
); err != nil {
4751
return err
4852
}
@@ -51,38 +55,48 @@ func (c *Generic) Apply(template *core.PodTemplateSpec) error {
5155
return nil
5256
}
5357

54-
func (c *Generic) GetEnvironments() *schedulerContainerResourcesApi.Environments {
55-
if c == nil || c.Environments == nil {
58+
func (g *Generic) GetEnvironments() *schedulerContainerResourcesApi.Environments {
59+
if g == nil || g.Environments == nil {
60+
return nil
61+
}
62+
63+
return g.Environments
64+
}
65+
66+
func (g *Generic) GetVolumeMounts() *schedulerContainerResourcesApi.VolumeMounts {
67+
if g == nil || g.VolumeMounts == nil {
5668
return nil
5769
}
5870

59-
return c.Environments
71+
return g.VolumeMounts
6072
}
6173

62-
func (c *Generic) With(other *Generic) *Generic {
63-
if c == nil && other == nil {
74+
func (g *Generic) With(other *Generic) *Generic {
75+
if g == nil && other == nil {
6476
return nil
6577
}
6678

67-
if c == nil {
79+
if g == nil {
6880
return other.DeepCopy()
6981
}
7082

7183
if other == nil {
72-
return c.DeepCopy()
84+
return g.DeepCopy()
7385
}
7486

7587
return &Generic{
76-
Environments: c.Environments.With(other.Environments),
88+
Environments: g.Environments.With(other.Environments),
89+
VolumeMounts: g.VolumeMounts.With(other.VolumeMounts),
7790
}
7891
}
7992

80-
func (c *Generic) Validate() error {
81-
if c == nil {
93+
func (g *Generic) Validate() error {
94+
if g == nil {
8295
return nil
8396
}
8497

8598
return shared.WithErrors(
86-
shared.PrefixResourceErrors("containerEnvironments", c.Environments.Validate()),
99+
shared.PrefixResourceErrors("containerEnvironments", g.Environments.Validate()),
100+
shared.PrefixResourceErrors("volumeMounts", g.VolumeMounts.Validate()),
87101
)
88102
}

pkg/apis/scheduler/v1alpha1/container/generic_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,13 @@ func Test_Generic(t *testing.T) {
7676
t.Run("Nil", func(t *testing.T) {
7777
applyGeneric(t, nil, nil)(func(t *testing.T, pod *core.PodTemplateSpec, spec *Generic) {
7878
require.Nil(t, spec.Environments)
79+
require.Nil(t, spec.VolumeMounts)
7980
})
8081
})
8182
t.Run("Empty template", func(t *testing.T) {
8283
applyGeneric(t, &core.PodTemplateSpec{})(func(t *testing.T, pod *core.PodTemplateSpec, spec *Generic) {
8384
require.Nil(t, spec.Environments)
85+
require.Nil(t, spec.VolumeMounts)
8486
})
8587
})
8688
t.Run("With fields", func(t *testing.T) {
@@ -99,7 +101,19 @@ func Test_Generic(t *testing.T) {
99101
},
100102
},
101103
},
104+
VolumeMounts: &schedulerContainerResourcesApi.VolumeMounts{
105+
VolumeMounts: []core.VolumeMount{
106+
{
107+
Name: "TEST",
108+
MountPath: "/data",
109+
},
110+
},
111+
},
102112
})(func(t *testing.T, pod *core.PodTemplateSpec, spec *Generic) {
113+
require.NotNil(t, spec.VolumeMounts)
114+
require.Len(t, spec.VolumeMounts.VolumeMounts, 1)
115+
require.EqualValues(t, "TEST", spec.VolumeMounts.VolumeMounts[0].Name)
116+
103117
// Spec
104118
require.NotNil(t, spec.Environments)
105119
require.Len(t, spec.Environments.Env, 1)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
21+
package resources
22+
23+
import (
24+
core "k8s.io/api/core/v1"
25+
26+
"github.com/arangodb/kube-arangodb/pkg/apis/scheduler/v1alpha1/interfaces"
27+
)
28+
29+
var _ interfaces.Container[Core] = &Core{}
30+
31+
type Core struct {
32+
// Entrypoint array. Not executed within a shell.
33+
// The container image's ENTRYPOINT is used if this is not provided.
34+
// Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
35+
// cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
36+
// to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
37+
// produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
38+
// of whether the variable exists or not. Cannot be updated.
39+
// +doc/link: Kubernetes Docs|https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
40+
Command []string `json:"command,omitempty"`
41+
42+
// Arguments to the entrypoint.
43+
// The container image's CMD is used if this is not provided.
44+
// Variable references $(VAR_NAME) are expanded using the container's environment. If a variable
45+
// cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced
46+
// to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will
47+
// produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless
48+
// of whether the variable exists or not. Cannot be updated.
49+
// +doc/link: Kubernetes Docs|https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
50+
Args []string `json:"args,omitempty"`
51+
52+
// Container's working directory.
53+
// If not specified, the container runtime's default will be used, which
54+
// might be configured in the container image.
55+
WorkingDir string `json:"workingDir,omitempty"`
56+
}
57+
58+
func (c *Core) Apply(_ *core.PodTemplateSpec, container *core.Container) error {
59+
if c == nil {
60+
return nil
61+
}
62+
63+
d := c.DeepCopy()
64+
65+
container.Args = d.Args
66+
container.Command = d.Command
67+
container.WorkingDir = d.WorkingDir
68+
69+
return nil
70+
}
71+
72+
func (c *Core) With(other *Core) *Core {
73+
if c == nil && other == nil {
74+
return nil
75+
}
76+
77+
if other == nil {
78+
return c.DeepCopy()
79+
}
80+
81+
return other.DeepCopy()
82+
}
83+
84+
func (c *Core) Validate() error {
85+
return nil
86+
}

0 commit comments

Comments
 (0)