Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/operator/clientutil/merge.go
4095 views
1
package clientutil
2
3
import (
4
"encoding/json"
5
"fmt"
6
7
v1 "k8s.io/api/core/v1"
8
"k8s.io/apimachinery/pkg/util/strategicpatch"
9
)
10
11
// MergePatchContainers adds patches to base using a strategic merge patch and
12
// iterating by container name, failing on the first error.
13
//
14
// Copied from github.com/prometheus-operator/prometheus-operator/pkg/k8sutil.
15
func MergePatchContainers(base, patches []v1.Container) ([]v1.Container, error) {
16
var out []v1.Container
17
18
// map of containers that still need to be patched by name
19
containersToPatch := make(map[string]v1.Container)
20
for _, c := range patches {
21
containersToPatch[c.Name] = c
22
}
23
24
for _, container := range base {
25
// If we have a patch result, iterate over each container and try and calculate the patch
26
if patchContainer, ok := containersToPatch[container.Name]; ok {
27
// Get the json for the container and the patch
28
containerBytes, err := json.Marshal(container)
29
if err != nil {
30
return nil, fmt.Errorf("failed to marshal json for container %s: %w", container.Name, err)
31
}
32
patchBytes, err := json.Marshal(patchContainer)
33
if err != nil {
34
return nil, fmt.Errorf("failed to marshal json for patch container %s: %w", container.Name, err)
35
}
36
37
// Calculate the patch result
38
jsonResult, err := strategicpatch.StrategicMergePatch(containerBytes, patchBytes, v1.Container{})
39
if err != nil {
40
return nil, fmt.Errorf("failed to generate merge patch for %s: %w", container.Name, err)
41
}
42
var patchResult v1.Container
43
if err := json.Unmarshal(jsonResult, &patchResult); err != nil {
44
return nil, fmt.Errorf("failed to unmarshal merged container %s: %w", container.Name, err)
45
}
46
47
// Add the patch result and remove the corresponding key from the to do list
48
out = append(out, patchResult)
49
delete(containersToPatch, container.Name)
50
} else {
51
// This container didn't need to be patched
52
out = append(out, container)
53
}
54
}
55
56
// Iterate over the patches and add all the containers that were not previously part of a patch result
57
for _, container := range patches {
58
if _, ok := containersToPatch[container.Name]; ok {
59
out = append(out, container)
60
}
61
}
62
63
return out, nil
64
}
65
66