Skip to content

Commit

Permalink
wip with all tests and reconciliations
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziosestito committed Oct 11, 2024
1 parent a3744dc commit 8658bfd
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 27 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ generate-controller: manifests ## Generate code containing DeepCopy, DeepCopyIn
manifests: ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./api/v1alpha1" paths="./internal/controller" output:crd:artifacts:config=helm/templates/crd output:rbac:artifacts:config=helm/templates/controller

.PHONY: generate-storage-test-crd
generate-storage-test-crd: ## Generate CRD used by the controller tests to access the storage resources. This is needed since storage does not provide CRD, being an API server extension.
$(CONTROLLER_GEN) crd paths="./api/storage/..." output:crd:artifacts:config=test/crd

.PHONY: generate-storage
generate-storage: ## Generate storage code in pkg/generated and DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
generate-storage: generate-storage-test-crd ## Generate storage code in pkg/generated and DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
API_KNOWN_VIOLATIONS_DIR=. UPDATE_API_KNOWN_VIOLATIONS=true ./hack/update-codegen.sh

.PHONY: generate-mocks
Expand Down
5 changes: 5 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ resources:
kind: Image
path: github.com/rancher/sbombastic/api/v1alpha1
version: v1alpha1
- controller: true
domain: sbombastic.rancher.io
group: storage.sbombastic.rancher.io
kind: SBOM
version: v1alpha1
version: "3"
4 changes: 4 additions & 0 deletions api/storage/v1alpha1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
Expand Down Expand Up @@ -51,6 +52,9 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ScanResultList{},
&SBOM{},
&SBOMList{},
&metav1.GetOptions{},
&metav1.CreateOptions{},
&metav1.ListOptions{},
)
return nil
}
8 changes: 8 additions & 0 deletions cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ func main() {
os.Exit(1)
}

if err = (&controller.SBOMReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "SBOM")
os.Exit(1)
}

// +kubebuilder:scaffold:builder

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.23.0
godebug default=go1.23

require (
github.com/google/uuid v1.6.0
github.com/nats-io/nats-server/v2 v2.10.21
github.com/nats-io/nats.go v1.37.0
github.com/onsi/ginkgo/v2 v2.20.2
Expand Down Expand Up @@ -57,7 +58,6 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/image_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ func (r *ImageReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
if err := r.Publisher.Publish(&msg); err != nil {
return ctrl.Result{}, fmt.Errorf("unable to publish CreateSBOM message: %w", err)
}
} else {
return ctrl.Result{}, fmt.Errorf("unable to fetch SBOM: %w", err)
}

return ctrl.Result{}, fmt.Errorf("unable to fetch SBOM: %w", err)
}

return ctrl.Result{}, nil
Expand Down
6 changes: 3 additions & 3 deletions internal/controller/image_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ import (
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

sbombasticv1alpha1 "github.com/rancher/sbombastic/api/v1alpha1"
"github.com/rancher/sbombastic/api/v1alpha1"
"github.com/rancher/sbombastic/internal/messaging"
messagingMocks "github.com/rancher/sbombastic/internal/messaging/mocks"
)

var _ = Describe("Image Controller", func() {
When("An Image without a SBOM is created", func() {
var reconciler ImageReconciler
var image sbombasticv1alpha1.Image
var image v1alpha1.Image

BeforeEach(func(ctx context.Context) {
By("Creating a new RegistryReconciler")
Expand All @@ -44,7 +44,7 @@ var _ = Describe("Image Controller", func() {
}

By("Creating the Image")
image = sbombasticv1alpha1.Image{
image = v1alpha1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: uuid.New().String(),
Namespace: "default",
Expand Down
137 changes: 120 additions & 17 deletions internal/controller/sbom_controller.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,122 @@
/*
Copyright 2024.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package controller

// ownerRef := metav1.GetControllerOf(&image)
// if ownerRef == nil {
// return ctrl.Result{}, errors.New("image does not have a Registry owner")
// }

// if ownerRef.Kind != "Registry" {
// return ctrl.Result{}, errors.New("image owner is not a Registry")
// }

// var registry v1alpha1.Registry
// err := r.Get(ctx, client.ObjectKey{
// Namespace: req.Namespace,
// Name: ownerRef.Name,
// }, &registry)
// if err != nil {
// return ctrl.Result{}, fmt.Errorf("unable to fetch Registry: %w", err)
// }
import (
"context"
"errors"
"fmt"
"time"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

storagev1alpha1 "github.com/rancher/sbombastic/api/storage/v1alpha1"
"github.com/rancher/sbombastic/api/v1alpha1"
)

// SBOMReconciler reconciles a SBOM object
type SBOMReconciler struct {
client.Client
Scheme *runtime.Scheme
}

// +kubebuilder:rbac:groups=storage.sbombastic.rancher.io.sbombastic.rancher.io,resources=sboms,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=storage.sbombastic.rancher.io.sbombastic.rancher.io,resources=sboms/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=storage.sbombastic.rancher.io.sbombastic.rancher.io,resources=sboms/finalizers,verbs=update

func (r *SBOMReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = log.FromContext(ctx)

var sbom storagev1alpha1.SBOM
if err := r.Get(ctx, req.NamespacedName, &sbom); err != nil {
if apierrors.IsNotFound(err) {
return ctrl.Result{}, nil
}

return ctrl.Result{}, fmt.Errorf("unable to fetch SBOM: %w", err)
}

registryName, found := sbom.Labels[v1alpha1.ImageRegistryLabel]
if !found {
return ctrl.Result{}, errors.New("SBOM does not have a registry label")
}

var sbomList storagev1alpha1.SBOMList
err := r.List(ctx, &sbomList, client.InNamespace(req.Namespace), client.MatchingLabelsSelector{
Selector: labels.SelectorFromSet(map[string]string{
v1alpha1.ImageRegistryLabel: registryName,
}),
})
if err != nil {
return ctrl.Result{}, fmt.Errorf("unable to list SBOMs: %w", err)
}

var imageList v1alpha1.ImageList
err = r.List(ctx, &imageList, client.InNamespace(req.Namespace), client.MatchingLabelsSelector{
Selector: labels.SelectorFromSet(map[string]string{
v1alpha1.ImageRegistryLabel: registryName,
}),
})
if err != nil {
return ctrl.Result{}, fmt.Errorf("unable to list Images: %w", err)
}

if len(sbomList.Items) == len(imageList.Items) {

Check failure on line 83 in internal/controller/sbom_controller.go

View workflow job for this annotation

GitHub Actions / Golangci-lint

`if len(sbomList.Items) == len(imageList.Items)` has complex nested blocks (complexity: 6) (nestif)
var registry v1alpha1.Registry
err := r.Get(ctx, client.ObjectKey{
Name: registryName,
Namespace: req.Namespace,
}, &registry)
if err != nil {
return ctrl.Result{}, fmt.Errorf("unable to fetch Registry: %w", err)
}

_, found := registry.Annotations[v1alpha1.RegistryLastDiscoveredAtAnnotation]
if !found {
if registry.Annotations == nil {
registry.Annotations = make(map[string]string)
}

registry.Annotations[v1alpha1.RegistryLastDiscoveredAtAnnotation] = time.Now().Format(time.RFC3339)
if err := r.Update(ctx, &registry); err != nil {
return ctrl.Result{}, fmt.Errorf("unable to update Registry LastScannedAt: %w", err)
}
}

return ctrl.Result{}, nil
}

return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *SBOMReconciler) SetupWithManager(mgr ctrl.Manager) error {
err := ctrl.NewControllerManagedBy(mgr).
// Uncomment the following line adding a pointer to an instance of the controlled resource as an argument
For(&storagev1alpha1.SBOM{}).
Complete(r)
if err != nil {
return fmt.Errorf("unable to create SBOM controller: %w", err)
}

return nil
}
7 changes: 6 additions & 1 deletion internal/controller/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ var _ = BeforeSuite(func() {

By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "helm", "templates", "crd")},
CRDDirectoryPaths: []string{
filepath.Join("..", "..", "helm", "templates", "crd"),
// Add storage CRD used only for testing.
// Storage does not need CRD, as it uses the API server extension mechanism.
filepath.Join("..", "..", "test", "crd"),
},
ErrorIfCRDPathMissing: true,

// The BinaryAssetsDirectory is only required if you want to run the tests directly
Expand Down
4 changes: 2 additions & 2 deletions pkg/generated/openapi/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8658bfd

Please sign in to comment.