Skip to content

Commit

Permalink
(server) Expose content URL on CR status
Browse files Browse the repository at this point in the history
closes #119

Signed-off-by: Anik <[email protected]>
  • Loading branch information
anik120 committed Sep 14, 2023
1 parent f9c6bcf commit fd8cef2
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 25 deletions.
1 change: 1 addition & 0 deletions api/core/v1alpha1/catalog_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type CatalogStatus struct {

ResolvedSource *CatalogSource `json:"resolvedSource,omitempty"`
Phase string `json:"phase,omitempty"`
ContentURL string `json:"contentURL,omitempty"`
}

// CatalogSource contains the sourcing information for a Catalog
Expand Down
11 changes: 7 additions & 4 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func main() {
systemNamespace string
storageDir string
catalogServerAddr string
httpExternalAddr string
)
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
Expand All @@ -84,6 +85,7 @@ func main() {
flag.StringVar(&systemNamespace, "system-namespace", "", "The namespace catalogd uses for internal state, configuration, and workloads")
flag.StringVar(&storageDir, "catalogs-storage-dir", "/var/cache/catalogs", "The directory in the filesystem where unpacked catalog content will be stored and served from")
flag.StringVar(&catalogServerAddr, "catalogs-server-addr", ":8083", "The address where the unpacked catalogs' content will be accessible")
flag.StringVar(&httpExternalAddr, "http-external-address", "http://localhost:8080", "The external address at which the http server is reachable.")
flag.BoolVar(&profiling, "profiling", false, "enable profiling endpoints to allow for using pprof")
flag.BoolVar(&catalogdVersion, "version", false, "print the catalogd version and exit")
opts := zap.Options{
Expand Down Expand Up @@ -135,7 +137,7 @@ func main() {
os.Exit(1)
}

localStorage = storage.LocalDir{RootDir: storageDir}
localStorage = storage.LocalDir{RootDir: storageDir, URLPrefix: "/catalogs/"}
shutdownTimeout := 30 * time.Second
catalogServer := server.Server{
Kind: "catalogs",
Expand All @@ -155,9 +157,10 @@ func main() {
}

if err = (&corecontrollers.CatalogReconciler{
Client: mgr.GetClient(),
Unpacker: unpacker,
Storage: localStorage,
Client: mgr.GetClient(),
Unpacker: unpacker,
Storage: localStorage,
HTTPExternalAddr: httpExternalAddr,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Catalog")
os.Exit(1)
Expand Down
2 changes: 2 additions & 0 deletions config/crd/bases/catalogd.operatorframework.io_catalogs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ spec:
- type
type: object
type: array
contentURL:
type: string
phase:
type: string
resolvedSource:
Expand Down
1 change: 1 addition & 0 deletions config/default/manager_auth_proxy_patch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ spec:
- "--leader-elect"
- "--catalogs-storage-dir=/var/cache/catalogs"
- "--feature-gates=CatalogMetadataAPI=true,HTTPServer=true"
- "--http-external-address=catalogd-catalogserver.catalogd-system.svc"

15 changes: 10 additions & 5 deletions pkg/controllers/core/catalog_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ const fbcDeletionFinalizer = "catalogd.operatorframework.io/delete-server-cache"
// CatalogReconciler reconciles a Catalog object
type CatalogReconciler struct {
client.Client
Unpacker source.Unpacker
Storage storage.Instance
Unpacker source.Unpacker
Storage storage.Instance
HTTPExternalAddr string
}

//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogs,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -138,21 +139,24 @@ func (r *CatalogReconciler) reconcile(ctx context.Context, catalog *v1alpha1.Cat
updateStatusUnpacking(&catalog.Status, unpackResult)
return ctrl.Result{}, nil
case source.StateUnpacked:
contentURL := ""
// TODO: We should check to see if the unpacked result has the same content
// as the already unpacked content. If it does, we should skip this rest
// of the unpacking steps.
if features.CatalogdFeatureGate.Enabled(features.HTTPServer) {
if err := r.Storage.Store(catalog.Name, unpackResult.FS); err != nil {
location, err := r.Storage.Store(catalog.Name, unpackResult.FS)
if err != nil {
return ctrl.Result{}, updateStatusStorageError(&catalog.Status, fmt.Errorf("error storing fbc: %v", err))
}
contentURL = fmt.Sprintf("%s%s", r.HTTPExternalAddr, location)
}
if features.CatalogdFeatureGate.Enabled(features.CatalogMetadataAPI) {
if err = r.syncCatalogMetadata(ctx, unpackResult.FS, catalog); err != nil {
return ctrl.Result{}, updateStatusUnpackFailing(&catalog.Status, fmt.Errorf("create catalog metadata objects: %v", err))
}
}

updateStatusUnpacked(&catalog.Status, unpackResult)
updateStatusUnpacked(&catalog.Status, unpackResult, contentURL)
return ctrl.Result{}, nil
default:
return ctrl.Result{}, updateStatusUnpackFailing(&catalog.Status, fmt.Errorf("unknown unpack state %q: %v", unpackResult.State, err))
Expand Down Expand Up @@ -181,8 +185,9 @@ func updateStatusUnpacking(status *v1alpha1.CatalogStatus, result *source.Result
})
}

func updateStatusUnpacked(status *v1alpha1.CatalogStatus, result *source.Result) {
func updateStatusUnpacked(status *v1alpha1.CatalogStatus, result *source.Result, contentURL string) {
status.ResolvedSource = result.ResolvedSource
status.ContentURL = contentURL
status.Phase = v1alpha1.PhaseUnpacked
meta.SetStatusCondition(&status.Conditions, metav1.Condition{
Type: v1alpha1.TypeUnpacked,
Expand Down
6 changes: 3 additions & 3 deletions pkg/controllers/core/catalog_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ type MockStore struct {
shouldError bool
}

func (m MockStore) Store(_ string, _ fs.FS) error {
func (m MockStore) Store(_ string, _ fs.FS) (string, error) {
if m.shouldError {
return errors.New("mockstore store error")
return "", errors.New("mockstore store error")
}
return nil
return "url", nil
}

func (m MockStore) Delete(_ string) error {
Expand Down
15 changes: 8 additions & 7 deletions pkg/storage/localdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ import (
// done so that clients accessing the content stored in RootDir/catalogName have
// atomic view of the content for a catalog.
type LocalDir struct {
RootDir string
RootDir string
URLPrefix string
}

func (s LocalDir) Store(catalog string, fsys fs.FS) error {
func (s LocalDir) Store(catalog string, fsys fs.FS) (string, error) {
fbcDir := filepath.Join(s.RootDir, catalog)
if err := os.MkdirAll(fbcDir, 0700); err != nil {
return err
return "", err

Check warning on line 26 in pkg/storage/localdir.go

View check run for this annotation

Codecov / codecov/patch

pkg/storage/localdir.go#L26

Added line #L26 was not covered by tests
}
tempFile, err := os.CreateTemp(s.RootDir, fmt.Sprint(catalog))
if err != nil {
return err
return "", err

Check warning on line 30 in pkg/storage/localdir.go

View check run for this annotation

Codecov / codecov/patch

pkg/storage/localdir.go#L30

Added line #L30 was not covered by tests
}
defer os.Remove(tempFile.Name())
err = declcfg.WalkMetasFS(fsys, func(path string, meta *declcfg.Meta, err error) error {
Expand All @@ -37,10 +38,10 @@ func (s LocalDir) Store(catalog string, fsys fs.FS) error {
return err
})
if err != nil {
return err
return "", err

Check warning on line 41 in pkg/storage/localdir.go

View check run for this annotation

Codecov / codecov/patch

pkg/storage/localdir.go#L41

Added line #L41 was not covered by tests
}
fbcFile := filepath.Join(fbcDir, "all.json")
return os.Rename(tempFile.Name(), fbcFile)
return fmt.Sprintf("%s%s/all.json", s.URLPrefix, catalog), os.Rename(tempFile.Name(), fbcFile)
}

func (s LocalDir) Delete(catalog string) error {
Expand All @@ -49,7 +50,7 @@ func (s LocalDir) Delete(catalog string) error {

func (s LocalDir) StorageServerHandler() http.Handler {
mux := http.NewServeMux()
mux.Handle("/catalogs/", http.StripPrefix("/catalogs/", http.FileServer(http.FS(&filesOnlyFilesystem{os.DirFS(s.RootDir)}))))
mux.Handle(s.URLPrefix, http.StripPrefix(s.URLPrefix, http.FileServer(http.FS(&filesOnlyFilesystem{os.DirFS(s.RootDir)}))))
return mux
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/storage/localdir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var _ = Describe("LocalDir Storage Test", func() {
})
When("An unpacked FBC is stored using LocalDir", func() {
BeforeEach(func() {
err := store.Store(catalog, unpackResultFS)
_, err := store.Store(catalog, unpackResultFS)
Expect(err).To(Not(HaveOccurred()))
})
It("should store the content in the RootDir correctly", func() {
Expand Down Expand Up @@ -88,7 +88,7 @@ var _ = Describe("LocalDir Server Handler tests", func() {
d, err := os.MkdirTemp(GinkgoT().TempDir(), "cache")
Expect(err).ToNot(HaveOccurred())
Expect(os.Mkdir(filepath.Join(d, "test-catalog"), 0700)).To(Succeed())
store = LocalDir{RootDir: d}
store = LocalDir{RootDir: d, URLPrefix: "/catalogs/"}
testServer = httptest.NewServer(store.StorageServerHandler())

})
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
// host's filesystem. It also a manager runnable object, that starts
// a server to serve the content stored.
type Instance interface {
Store(catalog string, fsys fs.FS) error
Store(catalog string, fsys fs.FS) (string, error)
Delete(catalog string) error
StorageServerHandler() http.Handler
}
6 changes: 3 additions & 3 deletions test/e2e/unpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ var _ = Describe("Catalog Unpacking", func() {
Expect(expectedBndl).To(komega.EqualObject(bndl, komega.IgnoreAutogeneratedMetadata))

By("Making sure the catalog content is available via the http server")
// (TODO): Get the URL from the CR once https://github.com/operator-framework/catalogd/issues/119 is done
catalogURL := fmt.Sprintf("%s.%s.svc/catalogs/%s/all.json", "catalogd-catalogserver", defaultSystemNamespace, catalogName)
err = c.Get(ctx, types.NamespacedName{Name: catalog.Name}, catalog)
Expect(err).ToNot(HaveOccurred())
job = batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: "test-svr-job",
Expand All @@ -189,7 +189,7 @@ var _ = Describe("Catalog Unpacking", func() {
{
Name: "test-svr",
Image: "curlimages/curl",
Command: []string{"sh", "-c", "curl --silent --show-error --location -o - " + catalogURL},
Command: []string{"sh", "-c", "curl --silent --show-error --location -o - " + catalog.Status.ContentURL},
},
},
RestartPolicy: "Never",
Expand Down

0 comments on commit fd8cef2

Please sign in to comment.