Skip to content

Commit d70f01f

Browse files
authored
⚠️ change catalog-specific URL from full path to API endpoint ref (#429)
* change catalog-specific URL from full path to API endpoint ref solves #427 and implements phase 1 of the CatalogD expandable interface. This phase just moves from `status.contentURL` to `status.baseURL`, and will be used to provide reference to the catalog-specific API instead of the full path to JSONLines-formatted content, plus tests and documentation. Signed-off-by: Jordan Keister <[email protected]> * sticking to catalog-centric reference, and updated type Signed-off-by: Jordan Keister <[email protected]> * remove some magic numbers Signed-off-by: Jordan Keister <[email protected]> * review reconciliation Signed-off-by: Jordan Keister <[email protected]> --------- Signed-off-by: Jordan Keister <[email protected]>
1 parent d320249 commit d70f01f

File tree

16 files changed

+159
-109
lines changed

16 files changed

+159
-109
lines changed

README.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,18 @@ Procedure steps marked with an asterisk (`*`) are likely to change with future A
3939
*Example output*
4040
```sh
4141
Name: operatorhubio
42-
Namespace:
42+
Namespace:
4343
Labels: olm.operatorframework.io/metadata.name=operatorhubio
4444
Annotations: <none>
4545
API Version: olm.operatorframework.io/v1alpha1
4646
Kind: ClusterCatalog
4747
Metadata:
48-
Creation Timestamp: 2024-09-12T13:37:04Z
48+
Creation Timestamp: 2024-10-17T13:48:46Z
4949
Finalizers:
5050
olm.operatorframework.io/delete-server-cache
5151
Generation: 1
52-
Resource Version: 961
53-
UID: fa6bb9cf-1a36-4189-a7a0-83284c3f6f55
52+
Resource Version: 7908
53+
UID: 34eeaa91-9f8e-4254-9937-0ae9d25e92df
5454
Spec:
5555
Priority: 0
5656
Source:
@@ -60,38 +60,38 @@ Procedure steps marked with an asterisk (`*`) are likely to change with future A
6060
Type: Image
6161
Status:
6262
Conditions:
63-
Last Transition Time: 2024-09-12T13:37:53Z
64-
Message: Successfully unpacked and stored content from quay.io/operatorhubio/catalog:latest
63+
Last Transition Time: 2024-10-17T13:48:59Z
64+
Message: Successfully unpacked and stored content from resolved source
65+
Observed Generation: 1
6566
Reason: Succeeded
6667
Status: False
6768
Type: Progressing
68-
Last Transition Time: 2024-09-12T13:37:53Z
69-
Message: Content from quay.io/operatorhubio/catalog:latest is being served
69+
Last Transition Time: 2024-10-17T13:48:59Z
70+
Message: Serving desired content from resolved source
71+
Observed Generation: 1
7072
Reason: Available
7173
Status: True
7274
Type: Serving
73-
Content URL: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/all.json
74-
Last Unpacked: 2024-09-12T13:37:52Z
75-
Observed Generation: 1
75+
Last Unpacked: 2024-10-17T13:48:58Z
7676
Resolved Source:
7777
Image:
78-
Last Poll Attempt: 2024-09-12T13:37:52Z
79-
Last Unpacked: 2024-09-12T13:37:52Z
80-
Ref: quay.io/operatorhubio/catalog:latest
81-
Resolved Ref: quay.io/operatorhubio/catalog@sha256:4453a361198d39d0390fd8c1a7f07b5a5a3ae1e8dac9979ef0c4eba46299df16
82-
Type: Image
83-
Events: <none>
78+
Last Successful Poll Attempt: 2024-10-17T14:49:59Z
79+
Ref: quay.io/operatorhubio/catalog@sha256:82be554b15ff246d8cc428f8d2f4cf5857c02ce3225d95d92a769ea3095e1fc7
80+
Type: Image
81+
Urls:
82+
Base: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio
83+
Events: <none>
8484
```
8585
8686
1. Port forward the `catalogd-service` service in the `olmv1-system` namespace:
8787
```sh
8888
$ kubectl -n olmv1-system port-forward svc/catalogd-service 8080:443
8989
```
9090
91-
1. Run the following command to get a list of packages:
91+
1. Access the `v1/all` service endpoint and filter the results to a list of packages by running the following command:
9292
9393
```sh
94-
$ curl -k https://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.package") | .name'
94+
$ curl https://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.package") | .name'
9595
```
9696
9797
*Example output*
@@ -118,7 +118,7 @@ Procedure steps marked with an asterisk (`*`) are likely to change with future A
118118
1. Run the following command to get a list of channels for the `ack-acm-controller` package:
119119
120120
```sh
121-
$ curl -k https://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "ack-acm-controller") | .name'
121+
$ curl https://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "ack-acm-controller") | .name'
122122
```
123123
124124
*Example output*
@@ -132,7 +132,7 @@ Procedure steps marked with an asterisk (`*`) are likely to change with future A
132132
1. Run the following command to get a list of bundles belonging to the `ack-acm-controller` package:
133133
134134
```sh
135-
$ curl -k https://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "ack-acm-controller") | .name'
135+
$ curl https://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "ack-acm-controller") | .name'
136136
```
137137
138138
*Example output*
@@ -153,7 +153,7 @@ Thanks for your interest in contributing to `catalogd`!
153153
154154
`catalogd` is in the very early stages of development and a more in depth contributing guide will come in the near future.
155155
156-
In the mean time, it is assumed you know how to make contributions to open source projects in general and this guide will only focus on how to manually test your changes (no automated testing yet).
156+
In the meantime, it is assumed you know how to make contributions to open source projects in general and this guide will only focus on how to manually test your changes (no automated testing yet).
157157
158158
If you have any questions, feel free to reach out to us on the Kubernetes Slack channel [#olm-dev](https://kubernetes.slack.com/archives/C0181L6JYQ2) or [create an issue](https://github.com/operator-framework/catalogd/issues/new)
159159
### Testing Local Changes

api/core/v1alpha1/clustercatalog_types.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,24 @@ type ClusterCatalogStatus struct {
147147
// type: Image
148148
// +optional
149149
ResolvedSource *ResolvedCatalogSource `json:"resolvedSource,omitempty"`
150-
// contentURL is a cluster-internal URL from which on-cluster components
151-
// can read the content of a catalog
150+
// urls contains the URLs that can be used to access the catalog.
152151
// +optional
153-
ContentURL string `json:"contentURL,omitempty"`
154-
152+
URLs *ClusterCatalogURLs `json:"urls,omitempty"`
155153
// lastUnpacked represents the time when the
156154
// ClusterCatalog object was last unpacked successfully.
157155
// +optional
158156
LastUnpacked metav1.Time `json:"lastUnpacked,omitempty"`
159157
}
160158

159+
// ClusterCatalogURLs contains the URLs that can be used to access the catalog.
160+
type ClusterCatalogURLs struct {
161+
// base is a required cluster-internal URL which provides API access for this ClusterCatalog.
162+
// A suffix API access path can be added to retrieve catalog data for the ClusterCatalog.
163+
// Currently, a 'v1' API access provides complete FBC retrival via the path "/api/v1/all", with the general form `{base}/api/v1/all`.
164+
// +kubebuilder:validation:Required
165+
Base string `json:"base"`
166+
}
167+
161168
// CatalogSource is a discriminated union of possible sources for a Catalog.
162169
// CatalogSource contains the sourcing information for a Catalog
163170
// +union

api/core/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/manager/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func main() {
258258
os.Exit(1)
259259
}
260260

261-
localStorage = storage.LocalDir{RootDir: storeDir, BaseURL: baseStorageURL}
261+
localStorage = storage.LocalDirV1{RootDir: storeDir, RootURL: baseStorageURL}
262262

263263
// Config for the the catalogd web server
264264
catalogServerConfig := serverutil.CatalogServerConfig{

config/base/crd/bases/olm.operatorframework.io_clustercatalogs.yaml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,6 @@ spec:
221221
- type
222222
type: object
223223
type: array
224-
contentURL:
225-
description: |-
226-
contentURL is a cluster-internal URL from which on-cluster components
227-
can read the content of a catalog
228-
type: string
229224
lastUnpacked:
230225
description: |-
231226
lastUnpacked represents the time when the
@@ -278,6 +273,19 @@ spec:
278273
x-kubernetes-validations:
279274
- message: source type 'Image' requires image field
280275
rule: self.type == 'Image' && has(self.image)
276+
urls:
277+
description: urls contains the URLs that can be used to access the
278+
catalog.
279+
properties:
280+
base:
281+
description: |-
282+
base is a required cluster-internal URL which provides API access for this ClusterCatalog.
283+
A suffix API access path can be added to retrieve catalog data for the ClusterCatalog.
284+
Currently, a 'v1' API access provides complete FBC retrival via the path "/api/v1/all", with the general form `{base}/api/v1/all`.
285+
type: string
286+
required:
287+
- base
288+
type: object
281289
type: object
282290
required:
283291
- metadata

docs/fetching-catalog-contents.md

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# `ClusterCatalog` Interface
2-
`catalogd` serves catalog content via an HTTP(S) endpoint
2+
`catalogd` serves catalog content via a catalog-specific, versioned HTTP(S) endpoint. Clients access catalog information via this API endpoint and a versioned reference of the desired format. Current support includes only a complete catalog download, indicated by the path "api/v1/all", for example if `status.urls.base` is `https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio` then `https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/vi/all` would receive the complete FBC for the catalog `operatorhubio`.
3+
34

45
## Response Format
5-
`catalogd` responses are encoded as a [JSON Lines](https://jsonlines.org/) stream of File-Based Catalog (FBC) [Meta](https://olm.operatorframework.io/docs/reference/file-based-catalogs/#schema) objects delimited by newlines.
6+
`catalogd` responses retrieved via the catalog-specific v1 API are encoded as a [JSON Lines](https://jsonlines.org/) stream of File-Based Catalog (FBC) [Meta](https://olm.operatorframework.io/docs/reference/file-based-catalogs/#schema) objects delimited by newlines.
67

78
### Example
89
For an example JSON-encoded FBC snippet
@@ -79,30 +80,32 @@ For example purposes we make the following assumption:
7980
For local development, consider skipping TLS verification, such as `curl -k`, or reference external material
8081
on self-signed certificate verification.
8182

82-
`ClusterCatalog` CRs have a status.contentURL field whose value is the location where the content
83-
of a catalog can be read from:
83+
`ClusterCatalog` CRs have a `status.urls.base` field which identifies the catalog-specific API to access the catalog content:
8484

8585
```yaml
8686
status:
8787
.
8888
.
89-
contentURL: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/all.json
89+
urls:
90+
base: https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio
9091
resolvedSource:
9192
image:
9293
ref: quay.io/operatorhubio/catalog@sha256:e53267559addc85227c2a7901ca54b980bc900276fc24d3f4db0549cb38ecf76
9394
type: Image
9495
```
9596
96-
9797
## On cluster
9898
99-
When making a request for the contents of the `operatorhubio` `ClusterCatalog` from within
100-
the cluster issue a HTTP `GET` request to
101-
`https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/all.json`
99+
When making a request for the complete contents of the `operatorhubio` `ClusterCatalog` from within
100+
the cluster, clients would combine `status.urls.base` with the desired API service and issue an HTTP GET request for the URL.
101+
102+
For example, to receive the complete catalog data for the `operatorhubio` catalog indicated above, the client would append the service point designator `api/v1/all`, like:
103+
104+
`https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/v1/all`.
102105

103106
An example command to run a `Pod` to `curl` the catalog contents:
104107
```sh
105-
kubectl run fetcher --image=curlimages/curl:latest -- curl https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/all.json
108+
kubectl run fetcher --image=curlimages/curl:latest -- curl https://catalogd-service.olmv1-system.svc/catalogs/operatorhubio/api/v1/all
106109
```
107110

108111
## Off cluster
@@ -115,11 +118,11 @@ kubectl -n olmv1-system port-forward svc/catalogd-service 8080:443
115118
```
116119

117120
Once the service has been successfully forwarded to a localhost port, issue a HTTP `GET`
118-
request to `https://localhost:8080/catalogs/operatorhubio/all.json`
121+
request to `https://localhost:8080/catalogs/operatorhubio/api/v1/all`
119122

120123
An example `curl` request that assumes the port-forwarding is mapped to port 8080 on the local machine:
121124
```sh
122-
curl http://localhost:8080/catalogs/operatorhubio/all.json
125+
curl http://localhost:8080/catalogs/operatorhubio/api/v1/all
123126
```
124127

125128
# Fetching `ClusterCatalog` contents from the `Catalogd` Service outside of the cluster
@@ -190,7 +193,7 @@ This section outlines a way of exposing the `Catalogd` Service's endpoints outsi
190193
1. Run the below example `curl` request to retrieve all of the catalog contents:
191194

192195
```sh
193-
$ curl https://<address>/catalogs/operatorhubio/all.json
196+
$ curl https://<address>/catalogs/operatorhubio/api/v1/all
194197
```
195198

196199
To obtain `address` of the ingress object, you can run the below command and look for the value in the `ADDRESS` field from output:

hack/scripts/demo-script.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ sleep 10
1111
kubectl apply -f https://github.com/operator-framework/catalogd/releases/latest/download/catalogd.yaml
1212
kubectl wait --for=condition=Available -n olmv1-system deploy/catalogd-controller-manager --timeout=60s
1313
sleep 10
14+
1415
# inspect crds (catalog)
1516
kubectl get crds -A
1617

@@ -19,15 +20,15 @@ kubectl apply -f config/samples/core_v1alpha1_catalog.yaml
1920
# shows catalog-sample
2021
kubectl get catalog -A
2122
# waiting for catalog to report ready status
22-
time kubectl wait --for=condition=Unpacked catalog/operatorhubio --timeout=1m
23+
time kubectl wait --for=condition=Serving catalog/operatorhubio --timeout=1m
2324

2425
# port forward the catalogd-service service to interact with the HTTP server serving catalog contents
2526
(kubectl -n olmv1-system port-forward svc/catalogd-service 8080:80)&
2627

2728
# check what 'packages' are available in this catalog
28-
curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.package") | .name'
29+
curl http://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.package") | .name'
2930
# check what channels are included in the wavefront package
30-
curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "wavefront") | .name'
31+
curl http://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "wavefront") | .name'
3132
# check what bundles are included in the wavefront package
32-
curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "wavefront") | .name'
33+
curl http://localhost:8080/catalogs/operatorhubio/api/v1/all | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "wavefront") | .name'
3334

hack/scripts/gzip-demo-script.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ time kubectl wait --for=condition=Unpacked clustercatalog/operatorhubio --timeou
1616
sleep 5
1717

1818
# retrieve catalog as plaintext JSONlines
19-
curl -k -vvv https://localhost:8080/catalogs/operatorhubio/all.json --output /tmp/cat-content.json
19+
curl -k -vvv https://localhost:8080/catalogs/operatorhubio/api/v1/all --output /tmp/cat-content.json
2020

2121
# advertise handling of compressed content
22-
curl -vvv -k https://localhost:8080/catalogs/operatorhubio/all.json -H 'Accept-Encoding: gzip' --output /tmp/cat-content.gz
22+
curl -vvv -k https://localhost:8080/catalogs/operatorhubio/api/v1/all -H 'Accept-Encoding: gzip' --output /tmp/cat-content.gz
2323

2424
# let curl handle the compress/decompress for us
25-
curl -vvv --compressed -k https://localhost:8080/catalogs/operatorhubio/all.json --output /tmp/cat-content-decompressed.txt
25+
curl -vvv --compressed -k https://localhost:8080/catalogs/operatorhubio/api/v1/all --output /tmp/cat-content-decompressed.txt
2626

2727
# show that there's no content change with changed format
2828
diff /tmp/cat-content.json /tmp/cat-content-decompressed.txt

internal/controllers/core/clustercatalog_controller.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func (r *ClusterCatalogReconciler) SetupWithManager(mgr ctrl.Manager) error {
159159
func (r *ClusterCatalogReconciler) reconcile(ctx context.Context, catalog *v1alpha1.ClusterCatalog) (ctrl.Result, error) {
160160
l := log.FromContext(ctx)
161161
// Check if the catalog availability is set to disabled, if true then
162-
// unset content URL, delete it from the cache and set appropriate status
162+
// unset base URL, delete it from the cache and set appropriate status
163163
if catalog.Spec.Availability == v1alpha1.AvailabilityDisabled {
164164
// Delete the catalog from local cache
165165
err := r.deleteCatalogCache(ctx, catalog)
@@ -244,10 +244,10 @@ func (r *ClusterCatalogReconciler) reconcile(ctx context.Context, catalog *v1alp
244244
updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), storageErr)
245245
return ctrl.Result{}, storageErr
246246
}
247-
contentURL := r.Storage.ContentURL(catalog.Name)
247+
baseURL := r.Storage.BaseURL(catalog.Name)
248248

249249
updateStatusProgressing(&catalog.Status, catalog.GetGeneration(), nil)
250-
updateStatusServing(&catalog.Status, *unpackResult, contentURL, catalog.GetGeneration())
250+
updateStatusServing(&catalog.Status, *unpackResult, baseURL, catalog.GetGeneration())
251251
default:
252252
panic(fmt.Sprintf("unknown unpack state %q", unpackResult.State))
253253
}
@@ -271,7 +271,7 @@ func (r *ClusterCatalogReconciler) getCurrentState(catalog *v1alpha1.ClusterCata
271271
// Set expected status based on what we see in the stored catalog
272272
clearUnknownConditions(expectedStatus)
273273
if hasStoredCatalog && r.Storage.ContentExists(catalog.Name) {
274-
updateStatusServing(expectedStatus, storedCatalog.unpackResult, r.Storage.ContentURL(catalog.Name), storedCatalog.observedGeneration)
274+
updateStatusServing(expectedStatus, storedCatalog.unpackResult, r.Storage.BaseURL(catalog.Name), storedCatalog.observedGeneration)
275275
updateStatusProgressing(expectedStatus, storedCatalog.observedGeneration, nil)
276276
}
277277

@@ -323,9 +323,12 @@ func updateStatusProgressing(status *v1alpha1.ClusterCatalogStatus, generation i
323323
meta.SetStatusCondition(&status.Conditions, progressingCond)
324324
}
325325

326-
func updateStatusServing(status *v1alpha1.ClusterCatalogStatus, result source.Result, contentURL string, generation int64) {
326+
func updateStatusServing(status *v1alpha1.ClusterCatalogStatus, result source.Result, baseURL string, generation int64) {
327327
status.ResolvedSource = result.ResolvedSource
328-
status.ContentURL = contentURL
328+
if status.URLs == nil {
329+
status.URLs = &v1alpha1.ClusterCatalogURLs{}
330+
}
331+
status.URLs.Base = baseURL
329332
status.LastUnpacked = metav1.NewTime(result.UnpackTime)
330333
meta.SetStatusCondition(&status.Conditions, metav1.Condition{
331334
Type: v1alpha1.TypeServing,
@@ -349,7 +352,7 @@ func updateStatusCatalogDisabled(status *v1alpha1.ClusterCatalogStatus, generati
349352

350353
func updateStatusNotServing(status *v1alpha1.ClusterCatalogStatus, generation int64) {
351354
status.ResolvedSource = nil
352-
status.ContentURL = ""
355+
status.URLs = nil
353356
status.LastUnpacked = metav1.Time{}
354357
meta.SetStatusCondition(&status.Conditions, metav1.Condition{
355358
Type: v1alpha1.TypeServing,

0 commit comments

Comments
 (0)