Skip to content

Perdasilva/helmer #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
do stuff
Signed-off-by: Per Goncalves da Silva <[email protected]>
  • Loading branch information
Per Goncalves da Silva committed Oct 10, 2024
commit 20106c7b9049fbd30418a798c90946e5ed80ed6e
13 changes: 10 additions & 3 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func main() {
Preflights: preflights,
}

helmer := &controllers.Engine{
helmEngine := &controllers.Engine{
Unpacker: &source.TarGZ{
BaseCachePath: filepath.Join(cachePath, "charts"),
},
Expand All @@ -298,11 +298,18 @@ func main() {
},
}

_ = &controllers.Engine{
olmEngine := &controllers.Engine{
Unpacker: unpacker,
Applier: olmApplier,
}

enginator := &controllers.Enginator{
Router: map[string]*controllers.Engine{
"helm": helmEngine,
},
DefaultEngine: olmEngine,
}

cm := contentmanager.NewManager(clientRestConfigMapper, mgr.GetConfig(), mgr.GetRESTMapper())
err = clusterExtensionFinalizers.Register(controllers.ClusterExtensionCleanupContentManagerCacheFinalizer, finalizers.FinalizerFunc(func(ctx context.Context, obj client.Object) (crfinalizer.Result, error) {
ext := obj.(*ocv1alpha1.ClusterExtension)
Expand All @@ -317,7 +324,7 @@ func main() {
if err = (&controllers.ClusterExtensionReconciler{
Client: cl,
Resolver: resolver,
Engine: helmer,
Enginator: enginator,
InstalledBundleGetter: &controllers.DefaultInstalledBundleGetter{ActionClientGetter: acg},
Finalizers: clusterExtensionFinalizers,
Manager: cm,
Expand Down
2 changes: 1 addition & 1 deletion config/samples/argocd-helm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ spec:
sourceType: Catalog
catalog:
packageName: argocd-helm
version: 7.6.6
version: 7.6.8
install:
namespace: argocd-helm
serviceAccount:
Expand Down
2 changes: 1 addition & 1 deletion config/samples/catalogd_operatorcatalog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ spec:
source:
type: Image
image:
ref: docker.io/perdasilva/catalog:test
ref: docker.io/perdasilva/catalog:2
pollInterval: 10m
39 changes: 39 additions & 0 deletions config/samples/metrics-server.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: metrics-server
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: metrics-server-installer
namespace: metrics-server
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metrics-server-cluster-admin-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: metrics-server-installer
namespace: metrics-server
---
apiVersion: olm.operatorframework.io/v1alpha1
kind: ClusterExtension
metadata:
name: metrics-server
spec:
source:
sourceType: Catalog
catalog:
packageName: metrics-server
version: 3.12.0
install:
namespace: metrics-server
serviceAccount:
name: metrics-server-installer
13 changes: 4 additions & 9 deletions internal/applier/helmer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"helm.sh/helm/v3/pkg/chart/loader"
"io"
"io/fs"
"path/filepath"
"strings"

"helm.sh/helm/v3/pkg/action"
Expand All @@ -28,11 +27,11 @@ type Helmer struct {
ActionClientGetter helmclient.ActionClientGetter
}

func loadChartFromFS(fsys fs.FS, chartDir string) (*chart.Chart, error) {
func loadChartFromFS(fsys fs.FS) (*chart.Chart, error) {
var files []*loader.BufferedFile

// Walk through the file system and gather the chart files
err := fs.WalkDir(fsys, chartDir, func(path string, d fs.DirEntry, err error) error {
err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
Expand All @@ -56,11 +55,7 @@ func loadChartFromFS(fsys fs.FS, chartDir string) (*chart.Chart, error) {
}

// Create a BufferedFile with the content
relativePath, err := filepath.Rel(chartDir, path)
if err != nil {
return err
}
files = append(files, &loader.BufferedFile{Name: relativePath, Data: content})
files = append(files, &loader.BufferedFile{Name: path, Data: content})

return nil
})
Expand All @@ -79,7 +74,7 @@ func loadChartFromFS(fsys fs.FS, chartDir string) (*chart.Chart, error) {
}

func (h *Helmer) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.ClusterExtension, objectLabels map[string]string, storageLabels map[string]string) ([]client.Object, string, error) {
chrt, err := loadChartFromFS(contentFS, ".")
chrt, err := loadChartFromFS(contentFS)
if err != nil {
return nil, "", err
}
Expand Down
41 changes: 38 additions & 3 deletions internal/controllers/clusterextension_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package controllers

import (
"context"
"encoding/json"
"errors"
"fmt"
"io/fs"
Expand Down Expand Up @@ -67,11 +68,35 @@ type Engine struct {
Applier
}

type Enginator struct {
Router map[string]*Engine
DefaultEngine *Engine
}

func (e *Enginator) GetEngine(bundle *declcfg.Bundle) (*Engine, error) {
contentType := ""
for _, property := range bundle.Properties {
if property.Type == "olm.content-type" {
if err := json.Unmarshal(property.Value, &contentType); err != nil {
return nil, fmt.Errorf("error unmarshalling package property: %w", err)
}
break
}
}
if contentType == "" {
return e.DefaultEngine, nil
}
if _, ok := e.Router[contentType]; !ok {
return nil, fmt.Errorf("unknown content type: %s", contentType)
}
return e.Router[contentType], nil
}

// ClusterExtensionReconciler reconciles a ClusterExtension object
type ClusterExtensionReconciler struct {
client.Client
Resolver resolve.Resolver
Engine *Engine
Enginator *Enginator
Manager contentmanager.Manager
controller crcontroller.Controller
cache cache.Cache
Expand Down Expand Up @@ -250,8 +275,18 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
Ref: resolvedBundle.Image,
},
}

engine, err := r.Enginator.GetEngine(resolvedBundle)
if err != nil {
// Wrap the error passed to this with the resolution information until we have successfully
// installed since we intend for the progressing condition to replace the resolved condition
// and will be removing the .status.resolution field from the ClusterExtension status API
setStatusProgressing(ext, wrapErrorWithResolutionInfo(resolvedBundleMetadata, err))
return ctrl.Result{}, err
}

l.Info("unpacking resolved bundle")
unpackResult, err := r.Engine.Unpack(ctx, bundleSource)
unpackResult, err := engine.Unpack(ctx, bundleSource)
if err != nil {
// Wrap the error passed to this with the resolution information until we have successfully
// installed since we intend for the progressing condition to replace the resolved condition
Expand Down Expand Up @@ -285,7 +320,7 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
// to ensure exponential backoff can occur:
// - Permission errors (it is not possible to watch changes to permissions.
// The only way to eventually recover from permission errors is to keep retrying).
managedObjs, _, err := r.Engine.Apply(ctx, unpackResult.Bundle, ext, objLbls, storeLbls)
managedObjs, _, err := engine.Apply(ctx, unpackResult.Bundle, ext, objLbls, storeLbls)
if err != nil {
setStatusProgressing(ext, wrapErrorWithResolutionInfo(resolvedBundleMetadata, err))
// If bundle is not already installed, set Installed status condition to False
Expand Down
40 changes: 26 additions & 14 deletions internal/rukpak/source/tgz.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"strings"

"github.com/containers/image/v5/pkg/blobinfocache/none"
"github.com/containers/image/v5/types"
Expand All @@ -30,6 +32,13 @@ func (i *TarGZ) Unpack(ctx context.Context, bundle *BundleSource) (*Result, erro
return nil, reconcile.TerminalError(fmt.Errorf("error parsing bundle, bundle %s has a nil image source", bundle.Name))
}

// Parse the URL
parsedURL, err := url.Parse(bundle.Image.Ref)
if err != nil {
return nil, reconcile.TerminalError(fmt.Errorf("error downloading bundle '%s': %v", bundle.Name, err))
}
fileName := path.Base(parsedURL.Path)

// Download the .tgz file
resp, err := http.Get(bundle.Image.Ref)
if err != nil {
Expand All @@ -48,22 +57,15 @@ func (i *TarGZ) Unpack(ctx context.Context, bundle *BundleSource) (*Result, erro
}
defer gzReader.Close()

unpackDir := path.Join(i.BaseCachePath, bundle.Name)
unpackDir := path.Join(i.BaseCachePath, bundle.Name, fileName)
err = os.MkdirAll(unpackDir, 0700)
if err != nil {
return nil, fmt.Errorf("error creating temporary directory: %w", err)
}
defer func() {
if err := os.RemoveAll(unpackDir); err != nil {
l.Error(err, "error removing temporary OCI layout directory")
}
}()

// Open a tar reader
tarReader := tar.NewReader(gzReader)

_hack := ""

topLevelDir := ""
// Extract tar contents
for {
header, err := tarReader.Next()
Expand All @@ -74,8 +76,21 @@ func (i *TarGZ) Unpack(ctx context.Context, bundle *BundleSource) (*Result, erro
return nil, reconcile.TerminalError(fmt.Errorf("error unpaking bundle '%s': %v", bundle.Name, err))
}

// On the first entry, capture the top-level directory
if topLevelDir == "" {
topLevelDir = strings.Split(header.Name, "/")[0]
}

// Strip the top-level directory from the path
relativePath := strings.TrimPrefix(header.Name, topLevelDir+"/")

if relativePath == "" {
// Skip the top-level directory itself
continue
}

// Construct the target file path
targetPath := filepath.Join(unpackDir, header.Name)
targetPath := filepath.Join(unpackDir, relativePath)

switch header.Typeflag {
case tar.TypeDir:
Expand All @@ -88,9 +103,6 @@ func (i *TarGZ) Unpack(ctx context.Context, bundle *BundleSource) (*Result, erro
if err := os.MkdirAll(filepath.Dir(targetPath), os.FileMode(0700)); err != nil {
return nil, reconcile.TerminalError(fmt.Errorf("error unpacking bundle '%s': %v", bundle.Name, err))
}
if _hack == "" {
_hack = filepath.Join(unpackDir, filepath.Dir(targetPath))
}

// Create a file
outFile, err := os.OpenFile(targetPath, os.O_CREATE|os.O_WRONLY, os.FileMode(header.Mode))
Expand All @@ -108,7 +120,7 @@ func (i *TarGZ) Unpack(ctx context.Context, bundle *BundleSource) (*Result, erro
}
}

return successHelmUnpackResult(bundle.Name, _hack, bundle.Image.Ref), nil
return successHelmUnpackResult(bundle.Name, unpackDir, bundle.Image.Ref), nil
}

func successHelmUnpackResult(bundleName, unpackPath string, chartgz string) *Result {
Expand Down