@@ -6,6 +6,7 @@ package hooks
6
6
import (
7
7
"context"
8
8
"encoding/json"
9
+ "fmt"
9
10
"net/http"
10
11
"testing"
11
12
@@ -16,11 +17,15 @@ import (
16
17
"github.com/zarf-dev/zarf/src/internal/agent/http/admission"
17
18
"github.com/zarf-dev/zarf/src/internal/agent/operations"
18
19
"github.com/zarf-dev/zarf/src/pkg/state"
20
+ "github.com/zarf-dev/zarf/src/pkg/transform"
21
+ "github.com/zarf-dev/zarf/src/test/testutil"
19
22
"github.com/zarf-dev/zarf/src/types"
20
23
v1 "k8s.io/api/admission/v1"
21
24
corev1 "k8s.io/api/core/v1"
22
25
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
26
"k8s.io/apimachinery/pkg/runtime"
27
+ "oras.land/oras-go/v2"
28
+ "oras.land/oras-go/v2/registry/remote"
24
29
)
25
30
26
31
func createFluxOCIRepoAdmissionRequest (t * testing.T , op v1.Operation , fluxOCIRepo * flux.OCIRepository ) * v1.AdmissionRequest {
@@ -35,6 +40,188 @@ func createFluxOCIRepoAdmissionRequest(t *testing.T, op v1.Operation, fluxOCIRep
35
40
}
36
41
}
37
42
43
+ type OCIArtifact struct {
44
+ Domain string
45
+ Namespace string
46
+ Tag string
47
+ }
48
+
49
+ func populateLocalRegistry (t * testing.T , ctx context.Context , localUrl string , artifact OCIArtifact ) error {
50
+ localReg , err := remote .NewRegistry (localUrl )
51
+ if err != nil {
52
+ return err
53
+ }
54
+ localReg .PlainHTTP = true
55
+
56
+ remoteReg , err := remote .NewRegistry (artifact .Domain )
57
+ if err != nil {
58
+ return err
59
+ }
60
+
61
+ src , err := remoteReg .Repository (ctx , artifact .Namespace )
62
+ if err != nil {
63
+ return err
64
+ }
65
+ dst , err := localReg .Repository (ctx , artifact .Namespace )
66
+ if err != nil {
67
+ return err
68
+ }
69
+ desc , err := oras .Copy (ctx , src , artifact .Tag , dst , artifact .Tag , oras .DefaultCopyOptions )
70
+ if err != nil {
71
+ return err
72
+ }
73
+ t .Log (desc )
74
+
75
+ hashedTag , err := transform .ImageTransformHost (localUrl , fmt .Sprintf ("%s/%s:%s" , artifact .Domain , artifact .Namespace , artifact .Tag ))
76
+ if err != nil {
77
+ return err
78
+ }
79
+
80
+ desc , err = oras .Copy (ctx , src , artifact .Tag , dst , hashedTag , oras .DefaultCopyOptions )
81
+ if err != nil {
82
+ return err
83
+ }
84
+ t .Log (desc )
85
+
86
+ return nil
87
+ }
88
+
89
+ func setupRegistry (t * testing.T , ctx context.Context ) (string , error ) {
90
+ localUrl := testutil .SetupInMemoryRegistry (ctx , t , 5000 )
91
+
92
+ localReg , err := remote .NewRegistry (localUrl )
93
+ localReg .PlainHTTP = true
94
+ if err != nil {
95
+ return "" , err
96
+ }
97
+ var artifacts = []OCIArtifact {
98
+ {
99
+ Domain : "ghcr.io" ,
100
+ Namespace : "stefanprodan/charts/podinfo" ,
101
+ Tag : "6.9.0" ,
102
+ },
103
+ {
104
+ Domain : "ghcr.io" ,
105
+ Namespace : "stefanprodan/podinfo" ,
106
+ Tag : "6.9.0" ,
107
+ },
108
+ }
109
+
110
+ for _ , art := range artifacts {
111
+ err := populateLocalRegistry (t , ctx , localUrl , art )
112
+ if err != nil {
113
+ return "" , err
114
+ }
115
+ }
116
+
117
+ return localUrl , nil
118
+ }
119
+
120
+ func TestFluxOCIHelmMutationWebhook (t * testing.T ) {
121
+ t .Parallel ()
122
+
123
+ ctx := context .Background ()
124
+ url , err := setupRegistry (t , ctx )
125
+ if err != nil {
126
+ panic (err )
127
+ }
128
+
129
+ tests := []admissionTest {
130
+ {
131
+ name : "should be mutated but not the tag" ,
132
+ admissionReq : createFluxOCIRepoAdmissionRequest (t , v1 .Create , & flux.OCIRepository {
133
+ ObjectMeta : metav1.ObjectMeta {
134
+ Name : "mutate-this" ,
135
+ },
136
+ Spec : flux.OCIRepositorySpec {
137
+ URL : "oci://ghcr.io/stefanprodan/charts/podinfo" ,
138
+ Reference : & flux.OCIRepositoryRef {
139
+ Tag : "6.9.0" ,
140
+ },
141
+ },
142
+ }),
143
+ patch : []operations.PatchOperation {
144
+ operations .ReplacePatchOperation (
145
+ "/spec/url" ,
146
+ "oci://localhost:5000/stefanprodan/charts/podinfo" ,
147
+ ),
148
+ operations .AddPatchOperation (
149
+ "/spec/secretRef" ,
150
+ fluxmeta.LocalObjectReference {Name : config .ZarfImagePullSecretName },
151
+ ),
152
+ operations .ReplacePatchOperation (
153
+ "/spec/ref/tag" ,
154
+ "6.9.0" ,
155
+ ),
156
+ operations .ReplacePatchOperation (
157
+ "/metadata/labels" ,
158
+ map [string ]string {
159
+ "zarf-agent" : "patched" ,
160
+ },
161
+ ),
162
+ },
163
+ code : http .StatusOK ,
164
+ },
165
+ {
166
+ name : "should be mutated" ,
167
+ admissionReq : createFluxOCIRepoAdmissionRequest (t , v1 .Create , & flux.OCIRepository {
168
+ ObjectMeta : metav1.ObjectMeta {
169
+ Name : "mutate-this" ,
170
+ },
171
+ Spec : flux.OCIRepositorySpec {
172
+ URL : "oci://ghcr.io/stefanprodan/podinfo" ,
173
+ Reference : & flux.OCIRepositoryRef {
174
+ Tag : "6.9.0" ,
175
+ },
176
+ },
177
+ }),
178
+ patch : []operations.PatchOperation {
179
+ operations .ReplacePatchOperation (
180
+ "/spec/url" ,
181
+ "oci://localhost:5000/stefanprodan/podinfo" ,
182
+ ),
183
+ operations .AddPatchOperation (
184
+ "/spec/secretRef" ,
185
+ fluxmeta.LocalObjectReference {Name : config .ZarfImagePullSecretName },
186
+ ),
187
+ operations .ReplacePatchOperation (
188
+ "/spec/ref/tag" ,
189
+ "6.9.0-zarf-2985051089" ,
190
+ ),
191
+ operations .ReplacePatchOperation (
192
+ "/metadata/labels" ,
193
+ map [string ]string {
194
+ "zarf-agent" : "patched" ,
195
+ },
196
+ ),
197
+ },
198
+ code : http .StatusOK ,
199
+ },
200
+ }
201
+
202
+ s := & state.State {RegistryInfo : types.RegistryInfo {
203
+ Address : url ,
204
+ PushUsername : "" ,
205
+ PushPassword : "" ,
206
+ PullUsername : "" ,
207
+ PullPassword : "" ,
208
+ }}
209
+ for _ , tt := range tests {
210
+ tt := tt
211
+ t .Run (tt .name , func (t * testing.T ) {
212
+ t .Parallel ()
213
+ c := createTestClientWithZarfState (ctx , t , s )
214
+ handler := admission .NewHandler ().Serve (ctx , NewOCIRepositoryMutationHook (ctx , c ))
215
+ if tt .svc != nil {
216
+ _ , err := c .Clientset .CoreV1 ().Services ("zarf" ).Create (ctx , tt .svc , metav1.CreateOptions {})
217
+ require .NoError (t , err )
218
+ }
219
+ rr := sendAdmissionRequest (t , tt .admissionReq , handler )
220
+ verifyAdmission (t , rr , tt )
221
+ })
222
+ }
223
+ }
224
+
38
225
func TestFluxOCIMutationWebhook (t * testing.T ) {
39
226
t .Parallel ()
40
227
0 commit comments