Skip to content

Commit

Permalink
add initial wiring of validation
Browse files Browse the repository at this point in the history
Fixes operator-framework#167

Signed-off-by: Austin Macdonald <austin@redhat.com>
  • Loading branch information
asmacdo committed Aug 23, 2022
1 parent aaba575 commit 577d61d
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 49 deletions.
8 changes: 8 additions & 0 deletions cmd/core/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"github.com/operator-framework/rukpak/internal/storage"
"github.com/operator-framework/rukpak/internal/uploadmgr"
"github.com/operator-framework/rukpak/internal/util"
"github.com/operator-framework/rukpak/internal/validators"
"github.com/operator-framework/rukpak/internal/version"
)

Expand Down Expand Up @@ -205,12 +206,19 @@ func main() {
os.Exit(1)
}

plainValidator, err := validators.NewPlainValidator()
if err != nil {
setupLog.Error(err, "unable to setup bundle validator")
os.Exit(1)
}

if err = (&plaincontrollers.BundleReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Storage: bundleStorage,
Finalizers: bundleFinalizers,
Unpacker: unpacker,
Validator: plainValidator,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", rukpakv1alpha1.BundleKind)
os.Exit(1)
Expand Down
17 changes: 17 additions & 0 deletions combo-bd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# TODO(asmacdo) dev only, remove before merge
apiVersion: core.rukpak.io/v1alpha1
kind: BundleDeployment
metadata:
name: combo
spec:
provisionerClassName: core.rukpak.io/plain
template:
metadata:
labels:
app: combo
spec:
provisionerClassName: core.rukpak.io/plain
source:
image:
ref: quay.io/operator-framework/combo-bundle:v0.0.2
type: image
52 changes: 4 additions & 48 deletions internal/provisioner/plain/controllers/bundle_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,13 @@ limitations under the License.
package controllers

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/fs"
"path/filepath"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
apimacherrors "k8s.io/apimachinery/pkg/util/errors"
apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -44,6 +37,7 @@ import (
"github.com/operator-framework/rukpak/internal/storage"
updater "github.com/operator-framework/rukpak/internal/updater/bundle"
"github.com/operator-framework/rukpak/internal/util"
"github.com/operator-framework/rukpak/internal/validators"
)

// BundleReconciler reconciles a Bundle object
Expand All @@ -53,6 +47,7 @@ type BundleReconciler struct {
Storage storage.Storage
Finalizers finalizer.Finalizers
Unpacker source.Unpacker
Validator validators.Validator
}

//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundles,verbs=list;watch;update;patch
Expand Down Expand Up @@ -146,15 +141,9 @@ func (r *BundleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
updateStatusUnpacking(&u, unpackResult)
return ctrl.Result{}, nil
case source.StateUnpacked:
objects, err := getObjects(unpackResult.Bundle)
if err != nil {
return ctrl.Result{}, updateStatusUnpackFailing(&u, fmt.Errorf("get objects from bundle manifests: %v", err))
}
if len(objects) == 0 {
return ctrl.Result{}, updateStatusUnpackFailing(&u, errors.New("invalid bundle: found zero objects: "+
"plain+v0 bundles are required to contain at least one object"))
if err = r.Validator.Validate(unpackResult.Bundle); err != nil {
return ctrl.Result{}, updateStatusUnpackFailing(&u, fmt.Errorf("Bundle Validation Errors: %v", err))
}

if err := r.Storage.Store(ctx, bundle, unpackResult.Bundle); err != nil {
return ctrl.Result{}, updateStatusUnpackFailing(&u, fmt.Errorf("persist bundle objects: %v", err))
}
Expand Down Expand Up @@ -228,39 +217,6 @@ func updateStatusUnpackFailing(u *updater.Updater, err error) error {
return err
}

func getObjects(bundleFS fs.FS) ([]client.Object, error) {
var objects []client.Object
const manifestsDir = "manifests"

entries, err := fs.ReadDir(bundleFS, manifestsDir)
if err != nil {
return nil, err
}
for _, e := range entries {
if e.IsDir() {
return nil, fmt.Errorf("subdirectories are not allowed within the %q directory of the bundle image filesystem: found %q", manifestsDir, filepath.Join(manifestsDir, e.Name()))
}
fileData, err := fs.ReadFile(bundleFS, filepath.Join(manifestsDir, e.Name()))
if err != nil {
return nil, err
}

dec := apimachyaml.NewYAMLOrJSONDecoder(bytes.NewReader(fileData), 1024)
for {
obj := unstructured.Unstructured{}
err := dec.Decode(&obj)
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return nil, fmt.Errorf("read %q: %v", e.Name(), err)
}
objects = append(objects, &obj)
}
}
return objects, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *BundleReconciler) SetupWithManager(mgr ctrl.Manager) error {
l := mgr.GetLogger().WithName("controller.bundle")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import (
"github.com/operator-framework/rukpak/internal/storage"
updater "github.com/operator-framework/rukpak/internal/updater/bundle-deployment"
"github.com/operator-framework/rukpak/internal/util"
"github.com/operator-framework/rukpak/internal/validators"
)

// BundleDeploymentReconciler reconciles a BundleDeployment object
Expand Down Expand Up @@ -370,7 +371,7 @@ func (r *BundleDeploymentReconciler) loadBundle(ctx context.Context, bundle *ruk
return nil, fmt.Errorf("load bundle: %v", err)
}

objects, err := getObjects(bundleFS)
objects, err := validators.GetObjects(bundleFS)
if err != nil {
return nil, fmt.Errorf("read bundle objects from bundle: %v", err)
}
Expand Down
53 changes: 53 additions & 0 deletions internal/validators/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package validators

import (
"bytes"
"errors"
"fmt"
"io"
"io/fs"
"path/filepath"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type Validator interface {
Validate(fs.FS) error
}

// TODO(asmacdo) I moved this *and* made it public, is this a problem?
func GetObjects(bundleFS fs.FS) ([]client.Object, error) {
var objects []client.Object
const manifestsDir = "manifests"

entries, err := fs.ReadDir(bundleFS, manifestsDir)
if err != nil {
return nil, err
}
for _, e := range entries {
if e.IsDir() {
return nil, fmt.Errorf("subdirectories are not allowed within the %q directory of the bundle image filesystem: found %q", manifestsDir, filepath.Join(manifestsDir, e.Name()))
}
fileData, err := fs.ReadFile(bundleFS, filepath.Join(manifestsDir, e.Name()))
if err != nil {
return nil, err
}

dec := apimachyaml.NewYAMLOrJSONDecoder(bytes.NewReader(fileData), 1024)
for {
obj := unstructured.Unstructured{}
err := dec.Decode(&obj)
if errors.Is(err, io.EOF) {
break
}
if err != nil {
// TODO(asmacdo) is this clear enough?
return nil, fmt.Errorf("read %q: %v", e.Name(), err)
}
objects = append(objects, &obj)
}
}
return objects, nil
}
41 changes: 41 additions & 0 deletions internal/validators/plain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package validators

import (
"errors"
"fmt"
"io/fs"
)

func NewPlainValidator() (Validator, error) {

return &plainValidator{}, nil
}

type plainValidator struct {
}

func (r *plainValidator) Validate(bundle fs.FS) error {
var validationErrors []error
objects, err := GetObjects(bundle)
if err != nil {
validationErrors = append(validationErrors, fmt.Errorf("get objects from bundle manifests: %v", err))
}
if len(objects) == 0 {
validationErrors = append(validationErrors, errors.New("invalid bundle: found zero objects: "+
"plain+v0 bundles are required to contain at least one object"))
}

// TODO(asmacdo) dev only, remove before merge
validationErrors = append(validationErrors, errors.New(""))
validationErrors = append(validationErrors, errors.New("hello"))
validationErrors = append(validationErrors, errors.New("world"))
validationErrors = append(validationErrors, errors.New("annnndd"))
validationErrors = append(validationErrors, errors.New("four Errors!"))
validationErrors = append(validationErrors, errors.New("moved this shit around!"))

err = errors.New("")
for _, each := range validationErrors {
err = fmt.Errorf("%v\n%v", err, each)
}
return err
}

0 comments on commit 577d61d

Please sign in to comment.