@@ -116,6 +116,113 @@ func TestOperatorControllerMetricsExportedEndpoint(t *testing.T) {
116
116
require .Contains (t , string (output ), "200 OK" , "Metrics endpoint did not return 200 OK" )
117
117
}
118
118
119
+ // nolint:gosec
120
+ // TestCatalogdMetricsExportedEndpoint verifies that the metrics endpoint for the catalogd
121
+ // is exported correctly and accessible by authorized users through RBAC and a ServiceAccount token.
122
+ // The test performs the following steps:
123
+ // 1. Creates a ClusterRoleBinding to grant necessary permissions for accessing metrics.
124
+ // 2. Generates a ServiceAccount token for authentication.
125
+ // 3. Deploys a curl pod to interact with the metrics endpoint.
126
+ // 4. Waits for the curl pod to become ready.
127
+ // 5. Executes a curl command from the pod to validate the metrics endpoint.
128
+ // 6. Cleans up all resources created during the test, such as the ClusterRoleBinding and curl pod.
129
+ func TestCatalogdMetricsExportedEndpoint (t * testing.T ) {
130
+ var (
131
+ token string
132
+ curlPod = "curl-metrics"
133
+ client = ""
134
+ clients = []string {"kubectl" , "oc" }
135
+ )
136
+
137
+ t .Log ("Looking for k8s client" )
138
+ for _ , c := range clients {
139
+ // Would prefer to use `command -v`, but even that may not be installed!
140
+ err := exec .Command (c , "version" , "--client" ).Run ()
141
+ if err == nil {
142
+ client = c
143
+ break
144
+ }
145
+ }
146
+ if client == "" {
147
+ t .Fatal ("k8s client not found" )
148
+ }
149
+ t .Logf ("Using %q as k8s client" , client )
150
+
151
+ t .Log ("Determining catalogd namespace" )
152
+ cmd := exec .Command (client , "get" , "pods" , "--all-namespaces" , "--selector=control-plane=catalogd-controller-manager" , "--output=jsonpath={.items[0].metadata.namespace}" )
153
+ output , err := cmd .CombinedOutput ()
154
+ require .NoError (t , err , "Error creating determining catalogd namespace: %s" , string (output ))
155
+ namespace := string (output )
156
+ if namespace == "" {
157
+ t .Fatal ("No catalogd namespace found" )
158
+ }
159
+ t .Logf ("Using %q as catalogd namespace" , namespace )
160
+
161
+ t .Log ("Creating ClusterRoleBinding for metrics access" )
162
+ cmd = exec .Command (client , "create" , "clusterrolebinding" , "catalogd-metrics-binding" ,
163
+ "--clusterrole=catalogd-metrics-reader" ,
164
+ "--serviceaccount=" + namespace + ":catalogd-controller-manager" )
165
+ output , err = cmd .CombinedOutput ()
166
+ require .NoError (t , err , "Error creating ClusterRoleBinding: %s" , string (output ))
167
+
168
+ defer func () {
169
+ t .Log ("Cleaning up ClusterRoleBinding" )
170
+ _ = exec .Command (client , "delete" , "clusterrolebinding" , "catalogd-metrics-binding" , "--ignore-not-found=true" ).Run ()
171
+ }()
172
+
173
+ t .Log ("Creating service account token for authentication" )
174
+ tokenCmd := exec .Command (client , "create" , "token" , "catalogd-controller-manager" , "-n" , namespace )
175
+ tokenOutput , tokenCombinedOutput , err := stdoutAndCombined (tokenCmd )
176
+ require .NoError (t , err , "Error creating token: %s" , string (tokenCombinedOutput ))
177
+ token = string (bytes .TrimSpace (tokenOutput ))
178
+
179
+ t .Log ("Creating a pod to run curl commands" )
180
+ cmd = exec .Command (client , "run" , curlPod ,
181
+ "--image=curlimages/curl:7.87.0" , "-n" , namespace ,
182
+ "--restart=Never" ,
183
+ "--overrides" , `{
184
+ "spec": {
185
+ "containers": [{
186
+ "name": "curl",
187
+ "image": "curlimages/curl:7.87.0",
188
+ "command": ["sh", "-c", "sleep 3600"],
189
+ "securityContext": {
190
+ "allowPrivilegeEscalation": false,
191
+ "capabilities": {
192
+ "drop": ["ALL"]
193
+ },
194
+ "runAsNonRoot": true,
195
+ "runAsUser": 1000,
196
+ "seccompProfile": {
197
+ "type": "RuntimeDefault"
198
+ }
199
+ }
200
+ }],
201
+ "serviceAccountName": "catalogd-controller-manager"
202
+ }
203
+ }` )
204
+ output , err = cmd .CombinedOutput ()
205
+ require .NoError (t , err , "Error creating curl pod: %s" , string (output ))
206
+
207
+ defer func () {
208
+ t .Log ("Cleaning up curl pod" )
209
+ _ = exec .Command (client , "delete" , "pod" , curlPod , "-n" , namespace , "--ignore-not-found=true" ).Run ()
210
+ }()
211
+
212
+ t .Log ("Waiting for the curl pod to become ready" )
213
+ waitCmd := exec .Command (client , "wait" , "--for=condition=Ready" , "pod" , curlPod , "-n" , namespace , "--timeout=60s" )
214
+ waitOutput , waitErr := waitCmd .CombinedOutput ()
215
+ require .NoError (t , waitErr , "Error waiting for curl pod to be ready: %s" , string (waitOutput ))
216
+
217
+ t .Log ("Validating the metrics endpoint" )
218
+ metricsURL := "https://catalogd-service." + namespace + ".svc.cluster.local:7443/metrics"
219
+ curlCmd := exec .Command (client , "exec" , curlPod , "-n" , namespace , "--" ,
220
+ "curl" , "-v" , "-k" , "-H" , "Authorization: Bearer " + token , metricsURL )
221
+ output , err = curlCmd .CombinedOutput ()
222
+ require .NoError (t , err , "Error calling metrics endpoint: %s" , string (output ))
223
+ require .Contains (t , string (output ), "200 OK" , "Metrics endpoint did not return 200 OK" )
224
+ }
225
+
119
226
func stdoutAndCombined (cmd * exec.Cmd ) ([]byte , []byte , error ) {
120
227
var outOnly bytes.Buffer
121
228
var outAndErr bytes.Buffer
0 commit comments