diff --git a/docs/api-reference/catalogd-api-reference.md b/docs/api-reference/catalogd-api-reference.md
index fa52fbc00..90ec13904 100644
--- a/docs/api-reference/catalogd-api-reference.md
+++ b/docs/api-reference/catalogd-api-reference.md
@@ -116,10 +116,26 @@ _Appears in:_
| --- | --- | --- | --- |
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | conditions is a representation of the current state for this ClusterCatalog.
The status is represented by a set of "conditions".
Each condition is generally structured in the following format:
- Type: a string representation of the condition type. More or less the condition "name".
- Status: a string representation of the state of the condition. Can be one of ["True", "False", "Unknown"].
- Reason: a string representation of the reason for the current state of the condition. Typically useful for building automation around particular Type+Reason combinations.
- Message: a human-readable message that further elaborates on the state of the condition.
The current set of condition types are:
- "Serving", which represents whether or not the contents of the catalog are being served via the HTTP(S) web server.
- "Progressing", which represents whether or not the ClusterCatalog is progressing towards a new state.
The current set of reasons are:
- "Succeeded", this reason is set on the "Progressing" condition when progressing to a new state is successful.
- "Blocked", this reason is set on the "Progressing" condition when the ClusterCatalog controller has encountered an error that requires manual intervention for recovery.
- "Retrying", this reason is set on the "Progressing" condition when the ClusterCatalog controller has encountered an error that might be resolvable on subsequent reconciliation attempts.
- "Available", this reason is set on the "Serving" condition when the contents of the ClusterCatalog are being served via an endpoint on the HTTP(S) web server.
- "Unavailable", this reason is set on the "Serving" condition when there is not an endpoint on the HTTP(S) web server that is serving the contents of the ClusterCatalog. | | |
| `resolvedSource` _[ResolvedCatalogSource](#resolvedcatalogsource)_ | resolvedSource contains information about the resolved source based on the source type.
Below is an example of a resolved source for an image source:
resolvedSource:
image:
lastSuccessfulPollAttempt: "2024-09-10T12:22:13Z"
ref: quay.io/operatorhubio/catalog@sha256:c7392b4be033da629f9d665fec30f6901de51ce3adebeff0af579f311ee5cf1b
type: Image | | |
-| `contentURL` _string_ | contentURL is a cluster-internal URL from which on-cluster components
can read the content of a catalog | | |
+| `urls` _[ClusterCatalogURLs](#clustercatalogurls)_ | urls contains the URLs that can be used to access the catalog. | | |
| `lastUnpacked` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#time-v1-meta)_ | lastUnpacked represents the time when the
ClusterCatalog object was last unpacked successfully. | | |
+#### ClusterCatalogURLs
+
+
+
+ClusterCatalogURLs contains the URLs that can be used to access the catalog.
+
+
+
+_Appears in:_
+- [ClusterCatalogStatus](#clustercatalogstatus)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `base` _string_ | base is a required cluster-internal URL which provides API access for this ClusterCatalog.
A suffix API access path can be added to retrieve catalog data for the ClusterCatalog.
Currently, a 'v1' API access provides complete FBC retrival via the path "/api/v1/all", with the general form `\{base\}/api/v1/all`. | | Required: \{\}
|
+
+
#### ImageSource
diff --git a/docs/api-reference/catalogd-webserver.md b/docs/api-reference/catalogd-webserver.md
index a95772ead..3aed2f6bd 100644
--- a/docs/api-reference/catalogd-webserver.md
+++ b/docs/api-reference/catalogd-webserver.md
@@ -3,18 +3,21 @@
[Catalogd](https://github.com/operator-framework/catalogd), the OLM v1 component for making catalog contents available on cluster, includes
a web server that serves catalog contents to clients via an HTTP(S) endpoint.
-The endpoint to retrieve this information is provided in the `.status.contentURL` of a `ClusterCatalog` resource.
-As an example:
+The endpoint to retrieve this information can be composed from the `.status.urls.base` of a `ClusterCatalog` resource with the selected access API path.
+As an example, to access the full FBC via the v1 API endpoint (indicated by path `api/v1/all`) where `.status.urls.base` is
```yaml
- contentURL: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/all.json
+ urls:
+ base: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio
```
+the URL to access the service would be `https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/v1/all`
+
!!! note
- The value of the `.status.contentURL` field in a `ClusterCatalog` resource is an arbitrary string value and can change at any time.
- While there are no guarantees on the exact value of this field, it will always be a URL that resolves successfully for clients using
- it to make a request from within the cluster.
+ The values of the `.status.urls` field in a `ClusterCatalog` resource are arbitrary string values and can change at any time.
+ While there are no guarantees on the exact value of this field, it will always contain catalog-specific API endpoints for use
+ by clients to make a request from within the cluster.
## Interacting With the Server
diff --git a/docs/howto/catalog-queries.md b/docs/howto/catalog-queries.md
index 4e6f260d7..7eadb8501 100644
--- a/docs/howto/catalog-queries.md
+++ b/docs/howto/catalog-queries.md
@@ -7,7 +7,7 @@ The following examples will show this default behavior, but for simplicity's sak
You can use the `curl` command with `jq` to query catalogs that are installed on your cluster.
``` terminal title="Query syntax"
-curl -k https://localhost:8443/catalogs/operatorhubio/all.json |
+curl -k https://localhost:8443/catalogs/operatorhubio/api/v1/all |
```
## Package queries
diff --git a/docs/tutorials/add-catalog.md b/docs/tutorials/add-catalog.md
index ad3ae06bb..2b75c666d 100644
--- a/docs/tutorials/add-catalog.md
+++ b/docs/tutorials/add-catalog.md
@@ -126,7 +126,8 @@ This catalog is distributed as an image [quay.io/operatorhubio/catalog](https://
Reason: Available
Status: True
Type: Serving
- Content URL: https://catalogd-server.olmv1-system.svc/catalogs/operatorhubio/all.json
+ URLs:
+ Base: https://catalogd-server.olmv1-system.svc/catalogs/operatorhubio
Last Unpacked: 2024-03-12T19:35:34Z
Resolved Source:
Image:
diff --git a/docs/tutorials/explore-available-content.md b/docs/tutorials/explore-available-content.md
index 67ea2127a..76bae2b6f 100644
--- a/docs/tutorials/explore-available-content.md
+++ b/docs/tutorials/explore-available-content.md
@@ -24,9 +24,9 @@ The following examples will show this default behavior, but for simplicity's sak
kubectl -n olmv1-system port-forward svc/catalogd-service 8443:443
```
-2. Return a list of all the extensions in a catalog:
+2. Return a list of all the extensions in a catalog via the v1 API endpoint:
``` terminal
- curl -k https://localhost:8443/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.package") | .name'
+ curl -k https://localhost:8443/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.package") | .name'
```
??? success
@@ -96,7 +96,7 @@ The following examples will show this default behavior, but for simplicity's sak
* Return list of packages that support `AllNamespaces` install mode and do not use webhooks:
``` terminal
- curl -k https://localhost:8443/catalogs/operatorhubio/all.json | jq -c 'select(.schema == "olm.bundle") | {"package":.package, "version":.properties[] | select(.type == "olm.bundle.object").value.data | @base64d | fromjson | select(.kind == "ClusterServiceVersion" and (.spec.installModes[] | select(.type == "AllNamespaces" and .supported == true) != null) and .spec.webhookdefinitions == null).spec.version}'
+ curl -k https://localhost:8443/catalogs/operatorhubio/api/v1/all | jq -c 'select(.schema == "olm.bundle") | {"package":.package, "version":.properties[] | select(.type == "olm.bundle.object").value.data | @base64d | fromjson | select(.kind == "ClusterServiceVersion" and (.spec.installModes[] | select(.type == "AllNamespaces" and .supported == true) != null) and .spec.webhookdefinitions == null).spec.version}'
```
??? success
@@ -127,7 +127,7 @@ The following examples will show this default behavior, but for simplicity's sak
3. Inspect the contents of an extension's metadata:
``` terminal
- curl -k https://localhost:8443/catalogs/operatorhubio/all.json | jq -s '.[] | select( .schema == "olm.package") | select( .name == "")'
+ curl -k https://localhost:8443/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select( .schema == "olm.package") | select( .name == "")'
```
`package_name`
diff --git a/go.mod b/go.mod
index ebd0d93b8..300498b3c 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/onsi/gomega v1.34.2
github.com/opencontainers/go-digest v1.0.0
github.com/operator-framework/api v0.27.0
- github.com/operator-framework/catalogd v0.33.0
+ github.com/operator-framework/catalogd v0.34.0
github.com/operator-framework/helm-operator-plugins v0.5.0
github.com/operator-framework/operator-registry v1.47.0
github.com/spf13/pflag v1.0.5
diff --git a/go.sum b/go.sum
index ae3144963..75efd1bdc 100644
--- a/go.sum
+++ b/go.sum
@@ -535,8 +535,8 @@ github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11 h1:eT
github.com/openshift/crd-schema-checker v0.0.0-20240404194209-35a9033b1d11/go.mod h1:EmVJt97N+pfWFsli/ipXTBZqSG5F5KGQhm3c3IsGq1o=
github.com/operator-framework/api v0.27.0 h1:OrVaGKZJvbZo58HTv2guz7aURkhVKYhFqZ/6VpifiXI=
github.com/operator-framework/api v0.27.0/go.mod h1:lg2Xx+S8NQWGYlEOvFwQvH46E5EK5IrAIL7HWfAhciM=
-github.com/operator-framework/catalogd v0.33.0 h1:hnLIFykO1FkjOAUFRPuYRIHQTE0oBF9jkGmWjKhxniQ=
-github.com/operator-framework/catalogd v0.33.0/go.mod h1:anZurjcFMBvbkuyqlJ98v9z+yjniPKqmhlyitk9DuBQ=
+github.com/operator-framework/catalogd v0.34.0 h1:zzCUTVrRJ4oCnjvAdairEWbUejLUnYRVsvAyhfREpyU=
+github.com/operator-framework/catalogd v0.34.0/go.mod h1:anZurjcFMBvbkuyqlJ98v9z+yjniPKqmhlyitk9DuBQ=
github.com/operator-framework/helm-operator-plugins v0.5.0 h1:qph2OoECcI9mpuUBtOsWOMgvpx52mPTTSvzVxICsT04=
github.com/operator-framework/helm-operator-plugins v0.5.0/go.mod h1:yVncrZ/FJNqedMil+055fk6sw8aMKRrget/AqGM0ig0=
github.com/operator-framework/operator-lib v0.15.0 h1:0QeRM4PMtThqINpcFGCEBnIV3Z8u7/8fYLEx6mUtdcM=
diff --git a/hack/tools/catalogs/download-catalog b/hack/tools/catalogs/download-catalog
index 43877690e..437cb8a75 100755
--- a/hack/tools/catalogs/download-catalog
+++ b/hack/tools/catalogs/download-catalog
@@ -53,12 +53,14 @@ if [ "$UNPACKED_CONDITION" != "True" ]; then
exit 1
fi
-# Get the contentURL
-CONTENT_URL=$(echo "$CLUSTER_CATALOG" | jq -r '.status.contentURL')
-if [ -z "$CONTENT_URL" ]; then
- echo "Content URL not found for ClusterCatalog $CATALOG_NAME."
+# Construct the API URL from the ClusterCatalog status
+CATALOG_API_URL=$(echo "$CLUSTER_CATALOG" | jq -r '.status.urls.base')
+if [ -z "$CATALOG_API_URL" ]; then
+ echo "ClusterCatalog $CATALOG_NAME does not express API endpoint in '.status.urls.base'."
exit 1
fi
+# Assemble the v1 API URL from the base endpoint
+CATALOG_CONTENT_URL="${CATALOG_API_URL}/api/v1/all"
# Start port forwarding
echo "Starting kubectl port-forward to $CATALOGD_SERVICE_NAME on port $CATALOGD_LOCAL_SERVICE_PORT..."
@@ -77,9 +79,9 @@ while ! curl -s "http://localhost:${CATALOGD_LOCAL_SERVICE_PORT}" >/dev/null; do
sleep 1
done
-# Modify the contentURL to hit localhost:
-LOCAL_CONTENT_URL=${CONTENT_URL//https:\/\/$CATALOGD_SERVICE_NAME.$CATALOGD_CATALOGD_SERVICE_NAMESPACE.svc/https:\/\/localhost:$CATALOGD_LOCAL_SERVICE_PORT}
-echo "Found content URL: $CONTENT_URL"
+# Modify the catalogd service endpoint URL to hit localhost:
+LOCAL_CONTENT_URL=${CATALOG_CONTENT_URL//https:\/\/$CATALOGD_SERVICE_NAME.$CATALOGD_CATALOGD_SERVICE_NAMESPACE.svc/https:\/\/localhost:$CATALOGD_LOCAL_SERVICE_PORT}
+echo "Calculated catalogd API pathcontent URL: $CATALOG_CONTENT_URL"
echo "Using local port: $CATALOGD_LOCAL_SERVICE_PORT"
echo "Using local content URL: $LOCAL_CONTENT_URL"
diff --git a/internal/catalogmetadata/client/client.go b/internal/catalogmetadata/client/client.go
index 43b972095..fee3b1cc2 100644
--- a/internal/catalogmetadata/client/client.go
+++ b/internal/catalogmetadata/client/client.go
@@ -7,6 +7,7 @@ import (
"io"
"io/fs"
"net/http"
+ "net/url"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -15,6 +16,10 @@ import (
"github.com/operator-framework/operator-registry/alpha/declcfg"
)
+const (
+ clusterCatalogV1ApiURL = "api/v1/all"
+)
+
type Cache interface {
// Get returns cache for a specified catalog name and version (resolvedRef).
//
@@ -113,7 +118,16 @@ func (c *Client) PopulateCache(ctx context.Context, catalog *catalogd.ClusterCat
}
func (c *Client) doRequest(ctx context.Context, catalog *catalogd.ClusterCatalog) (*http.Response, error) {
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, catalog.Status.ContentURL, nil)
+ if catalog.Status.URLs == nil {
+ return nil, fmt.Errorf("error: catalog %q has a nil status.urls value", catalog.Name)
+ }
+
+ catalogdURL, err := url.JoinPath(catalog.Status.URLs.Base, clusterCatalogV1ApiURL)
+ if err != nil {
+ return nil, fmt.Errorf("error forming catalogd API endpoint: %v", err)
+ }
+
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, catalogdURL, nil)
if err != nil {
return nil, fmt.Errorf("error forming request: %v", err)
}
diff --git a/internal/catalogmetadata/client/client_test.go b/internal/catalogmetadata/client/client_test.go
index 92645bdbf..33f43c1cf 100644
--- a/internal/catalogmetadata/client/client_test.go
+++ b/internal/catalogmetadata/client/client_test.go
@@ -28,7 +28,9 @@ func defaultCatalog() *catalogd.ClusterCatalog {
ResolvedSource: &catalogd.ResolvedCatalogSource{Image: &catalogd.ResolvedImageSource{
Ref: "fake/catalog@sha256:fakesha",
}},
- ContentURL: "https://fake-url.svc.local/all.json",
+ URLs: &catalogd.ClusterCatalogURLs{
+ Base: "https://fake-url.svc.local/catalogs/catalog-1",
+ },
},
}
}