7
7
"testing/fstest"
8
8
9
9
corev1 "k8s.io/api/core/v1"
10
+ utilerrors "k8s.io/apimachinery/pkg/util/errors"
11
+ "k8s.io/apimachinery/pkg/util/sets"
10
12
"sigs.k8s.io/controller-runtime/pkg/client"
11
13
12
14
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
@@ -28,54 +30,49 @@ func (o *ConfigMaps) Unpack(ctx context.Context, bundle *rukpakv1alpha1.Bundle)
28
30
configMapSources := bundle .Spec .Source .ConfigMaps
29
31
30
32
bundleFS := fstest.MapFS {}
33
+ seenFilepaths := map [string ]sets.Set [string ]{}
34
+
31
35
for _ , cmSource := range configMapSources {
32
36
cmName := cmSource .ConfigMap .Name
33
37
dir := filepath .Clean (cmSource .Path )
34
38
35
- // Check for paths outside the bundle root is handled in the bundle validation webhook
36
- // if strings.HasPrefix("../", dir) { ... }
39
+ // Validating admission webhook handles validation for:
40
+ // - paths outside the bundle root
41
+ // - configmaps referenced by bundles must be immutable
37
42
38
43
var cm corev1.ConfigMap
39
44
if err := o .Reader .Get (ctx , client.ObjectKey {Name : cmName , Namespace : o .ConfigMapNamespace }, & cm ); err != nil {
40
45
return nil , fmt .Errorf ("get configmap %s/%s: %v" , o .ConfigMapNamespace , cmName , err )
41
46
}
42
47
43
- // TODO: move configmaps immutability check to webhooks
44
- // This would require the webhook to lookup referenced configmaps.
45
- // We would need to implement this in two places:
46
- // 1. During bundle create:
47
- // - if referenced configmap already exists, ensure it is immutable
48
- // - if referenced configmap does not exist, allow the bundle to be created anyway
49
- // 2. During configmap create:
50
- // - if the configmap is referenced by a bundle, ensure it is immutable
51
- // - if not referenced by a bundle, allow the configmap to be created.
52
- if cm .Immutable == nil || * cm .Immutable == false {
53
- return nil , fmt .Errorf ("configmap %s/%s is mutable: all bundle configmaps must be immutable" , o .ConfigMapNamespace , cmName )
48
+ addToBundle := func (configMapName , filename string , data []byte ) {
49
+ filepath := filepath .Join (dir , filename )
50
+ if _ , ok := seenFilepaths [filepath ]; ! ok {
51
+ seenFilepaths [filepath ] = sets .New [string ]()
52
+ }
53
+ seenFilepaths [filepath ].Insert (configMapName )
54
+ bundleFS [filepath ] = & fstest.MapFile {
55
+ Data : data ,
56
+ }
54
57
}
55
-
56
- files := map [string ][]byte {}
57
58
for filename , data := range cm .Data {
58
- files [ filename ] = []byte (data )
59
+ addToBundle ( cmName , filename , []byte (data ) )
59
60
}
60
61
for filename , data := range cm .BinaryData {
61
- files [ filename ] = data
62
+ addToBundle ( cmName , filename , data )
62
63
}
64
+ }
63
65
64
- seenFilepaths := map [string ]string {}
65
- for filename , data := range files {
66
- filepath := filepath .Join (dir , filename )
67
-
68
- // forbid multiple configmaps in the list from referencing the same destination file.
69
- if existingCmName , ok := seenFilepaths [filepath ]; ok {
70
- return nil , fmt .Errorf ("configmap %s/%s contains path %q which is already referenced by configmap %s/%s" ,
71
- o .ConfigMapNamespace , cmName , filepath , o .ConfigMapNamespace , existingCmName )
72
- }
73
- seenFilepaths [filepath ] = cmName
74
- bundleFS [filepath ] = & fstest.MapFile {
75
- Data : data ,
76
- }
66
+ errs := []error {}
67
+ for filepath , cmNames := range seenFilepaths {
68
+ if len (cmNames ) > 1 {
69
+ errs = append (errs , fmt .Errorf ("duplicate path %q found in configmaps %v" , filepath , sets .List (cmNames )))
70
+ continue
77
71
}
78
72
}
73
+ if len (errs ) > 0 {
74
+ return nil , utilerrors .NewAggregate (errs )
75
+ }
79
76
80
77
resolvedSource := & rukpakv1alpha1.BundleSource {
81
78
Type : rukpakv1alpha1 .SourceTypeConfigMaps ,
0 commit comments