@@ -116,6 +116,113 @@ func TestOperatorControllerMetricsExportedEndpoint(t *testing.T) {
116116 require .Contains (t , string (output ), "200 OK" , "Metrics endpoint did not return 200 OK" )
117117}
118118
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+
119226func stdoutAndCombined (cmd * exec.Cmd ) ([]byte , []byte , error ) {
120227 var outOnly bytes.Buffer
121228 var outAndErr bytes.Buffer
0 commit comments