Skip to content
This repository was archived by the owner on Dec 15, 2021. It is now read-only.

Commit ac91c1e

Browse files
authored
Merge deployment containers as well (#1114)
1 parent ff0ba5b commit ac91c1e

File tree

3 files changed

+148
-38
lines changed

3 files changed

+148
-38
lines changed

docs/function-controller-configuration.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ data:
2323
"template": {
2424
"annotations": {
2525
"annotations-to-pod": "value"
26-
}
26+
},
27+
"containers": [{
28+
"resources": {
29+
"requests": {
30+
"cpu": "100m"
31+
}
32+
}
33+
}]
2734
}
2835
}
2936
}

pkg/utils/k8sutil.go

+22-5
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,29 @@ func MergeDeployments(destinationDeployment *appsv1.Deployment, sourceDeployment
374374
initializeEmptyMapsInDeployment(destinationDeployment)
375375
initializeEmptyMapsInDeployment(sourceDeployment)
376376
err := mergo.Merge(destinationDeployment, sourceDeployment)
377-
if err == nil && len(sourceDeployment.Spec.Template.Spec.Containers) > 0 && len(sourceDeployment.Spec.Template.Spec.Containers[0].VolumeMounts) > 0 {
378-
// cannot use sourceDeployment.Spec.Template.Spec.Containers[0].VolumeMounts (type []"k8s.io/api/core/v1".VolumeMount) as type "k8s.io/api/core/v1".VolumeMount in append
379-
// so iterate over and append
380-
for _, volumeMount := range sourceDeployment.Spec.Template.Spec.Containers[0].VolumeMounts {
381-
destinationDeployment.Spec.Template.Spec.Containers[0].VolumeMounts = append(destinationDeployment.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMount)
377+
378+
// Merge containers
379+
if err == nil && len(sourceDeployment.Spec.Template.Spec.Containers) > 0 {
380+
srcContainers := sourceDeployment.Spec.Template.Spec.Containers
381+
dstContainers := destinationDeployment.Spec.Template.Spec.Containers
382+
383+
// Merge each container individually
384+
for i, srcContainer := range srcContainers {
385+
if i >= len(dstContainers) {
386+
destinationDeployment.Spec.Template.Spec.Containers[i] = srcContainer
387+
continue
388+
}
389+
390+
dstContainer := dstContainers[i]
391+
392+
// Use mergo.WithAppendSlice to append extra volumeMount/env/port definitions
393+
err = mergo.Merge(&dstContainer, srcContainer, mergo.WithAppendSlice)
394+
if err != nil {
395+
break
396+
}
397+
destinationDeployment.Spec.Template.Spec.Containers[i] = dstContainer
382398
}
399+
383400
}
384401
return err
385402
}

pkg/utils/k8sutil_test.go

+118-32
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
corev1 "k8s.io/api/core/v1"
1313
extensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
1414
fakeextensionsapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
15+
resource "k8s.io/apimachinery/pkg/api/resource"
1516
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1617
"k8s.io/apimachinery/pkg/runtime/schema"
1718
"k8s.io/client-go/kubernetes/fake"
@@ -125,65 +126,150 @@ func TestInitializeEmptyMapsInDeployment(t *testing.T) {
125126
}
126127

127128
func TestMergeDeployments(t *testing.T) {
128-
var replicas int32
129-
replicas = 10
130-
volumeMount := corev1.VolumeMount{
131-
Name: "foo",
132-
MountPath: "/bar",
133-
}
134-
container := corev1.Container{
135-
VolumeMounts: []corev1.VolumeMount{
136-
volumeMount,
129+
var dstReplicas int32
130+
dstReplicas = 10
131+
destinationDeployment := appsv1.Deployment{
132+
ObjectMeta: metav1.ObjectMeta{
133+
Annotations: map[string]string{
134+
"foo1-deploy": "bar",
135+
},
137136
},
138-
}
139-
podSpec := corev1.PodSpec{
140-
Containers: []corev1.Container{
141-
container,
137+
Spec: appsv1.DeploymentSpec{
138+
Replicas: &dstReplicas,
139+
Template: corev1.PodTemplateSpec{
140+
Spec: corev1.PodSpec{
141+
Containers: []corev1.Container{
142+
{
143+
VolumeMounts: []corev1.VolumeMount{
144+
{
145+
Name: "foo",
146+
MountPath: "/bar",
147+
},
148+
},
149+
Resources: corev1.ResourceRequirements{},
150+
},
151+
},
152+
},
153+
},
142154
},
143155
}
144-
template := corev1.PodTemplateSpec{
145-
Spec: podSpec,
146-
}
147156

148-
destinationDeployment := appsv1.Deployment{
157+
var srcReplicas int32
158+
srcReplicas = 8
159+
sourceDeployment := appsv1.Deployment{
149160
ObjectMeta: metav1.ObjectMeta{
150161
Annotations: map[string]string{
151-
"foo1-deploy": "bar",
162+
"foo2-deploy": "bar",
163+
},
164+
},
165+
Spec: appsv1.DeploymentSpec{
166+
Replicas: &srcReplicas,
167+
Template: corev1.PodTemplateSpec{
168+
Spec: corev1.PodSpec{
169+
Containers: []corev1.Container{
170+
{
171+
VolumeMounts: []corev1.VolumeMount{
172+
{
173+
Name: "baz",
174+
MountPath: "/qux",
175+
},
176+
},
177+
Resources: corev1.ResourceRequirements{
178+
Requests: corev1.ResourceList{
179+
corev1.ResourceName(corev1.ResourceCPU): resource.MustParse("100m"),
180+
corev1.ResourceName(corev1.ResourceMemory): resource.MustParse("100Mi"),
181+
},
182+
},
183+
},
184+
},
185+
},
152186
},
153187
},
154188
}
155189

156-
sourceDeployment := appsv1.Deployment{
190+
var expectedReplicas int32
191+
expectedReplicas = 10
192+
expectedDeployment := appsv1.Deployment{
157193
ObjectMeta: metav1.ObjectMeta{
158194
Annotations: map[string]string{
195+
"foo1-deploy": "bar",
159196
"foo2-deploy": "bar",
160197
},
161198
},
162199
Spec: appsv1.DeploymentSpec{
163-
Replicas: &replicas,
164-
Template: template,
200+
Replicas: &expectedReplicas,
201+
Template: corev1.PodTemplateSpec{
202+
Spec: corev1.PodSpec{
203+
Containers: []corev1.Container{
204+
{
205+
VolumeMounts: []corev1.VolumeMount{
206+
{
207+
Name: "foo",
208+
MountPath: "/bar",
209+
},
210+
{
211+
Name: "baz",
212+
MountPath: "/qux",
213+
},
214+
},
215+
Resources: corev1.ResourceRequirements{
216+
Requests: corev1.ResourceList{
217+
corev1.ResourceName(corev1.ResourceCPU): resource.MustParse("100m"),
218+
corev1.ResourceName(corev1.ResourceMemory): resource.MustParse("100Mi"),
219+
},
220+
},
221+
},
222+
},
223+
},
224+
},
165225
},
166226
}
167227

168228
MergeDeployments(&destinationDeployment, &sourceDeployment)
169-
expectedAnnotations := map[string]string{
170-
"foo1-deploy": "bar",
171-
"foo2-deploy": "bar",
229+
230+
mergedContainerCount := len(destinationDeployment.Spec.Template.Spec.Containers)
231+
if mergedContainerCount != 1 {
232+
t.Fatalf("Expecting 1 container but received %v", mergedContainerCount)
172233
}
173-
expectedVolumneMounts := len(destinationDeployment.Spec.Template.Spec.Containers[0].VolumeMounts)
174-
mergedVolumneMounts := len(sourceDeployment.Spec.Template.Spec.Containers[0].VolumeMounts)
234+
235+
expectedAnnotations := expectedDeployment.ObjectMeta.Annotations
236+
mergedAnnotations := destinationDeployment.ObjectMeta.Annotations
175237
for i := range expectedAnnotations {
176-
if destinationDeployment.ObjectMeta.Annotations[i] != expectedAnnotations[i] {
177-
t.Fatalf("Expecting annotation %s but received %s", destinationDeployment.ObjectMeta.Annotations[i], expectedAnnotations[i])
238+
if mergedAnnotations[i] != expectedAnnotations[i] {
239+
t.Fatalf("Expecting annotation %s but received %s", expectedAnnotations[i], mergedAnnotations[i])
178240
}
179241
}
180-
if *destinationDeployment.Spec.Replicas != replicas {
181-
t.Fatalf("Expecting replicas as 10 but received %v", *destinationDeployment.Spec.Replicas)
242+
243+
mergedReplicas := *destinationDeployment.Spec.Replicas
244+
if mergedReplicas != expectedReplicas {
245+
t.Fatalf("Expecting 8 replicas but received %v", *destinationDeployment.Spec.Replicas)
182246
}
183-
if mergedVolumneMounts != expectedVolumneMounts {
184-
t.Fatalf("Expecting %v volumeMounts but received %v", expectedVolumneMounts, mergedVolumneMounts)
247+
248+
expectedVolumeMountCount := 2
249+
mergedVolumeMountCount := len(destinationDeployment.Spec.Template.Spec.Containers[0].VolumeMounts)
250+
if mergedVolumeMountCount != expectedVolumeMountCount {
251+
t.Fatalf("Expecting %v volumeMounts but received %v", expectedVolumeMountCount, mergedVolumeMountCount)
185252
}
186253

254+
expectedCPURequest := expectedDeployment.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceName(corev1.ResourceCPU)]
255+
mergedCPURequest := destinationDeployment.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceName(corev1.ResourceCPU)]
256+
if mergedCPURequest != expectedCPURequest {
257+
t.Fatalf(
258+
"Expecting %s cpu resource request but received %s",
259+
expectedCPURequest.String(),
260+
mergedCPURequest.String(),
261+
)
262+
}
263+
264+
expectedMemoryRequest := expectedDeployment.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceName(corev1.ResourceMemory)]
265+
mergedMemoryRequest := destinationDeployment.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceName(corev1.ResourceMemory)]
266+
if mergedMemoryRequest != expectedMemoryRequest {
267+
t.Fatalf(
268+
"Expecting %s memory resource request but received %s",
269+
expectedMemoryRequest.String(),
270+
mergedMemoryRequest.String(),
271+
)
272+
}
187273
}
188274

189275
func TestGetAnnotationsFromCRD(t *testing.T) {

0 commit comments

Comments
 (0)