Skip to content

Commit

Permalink
fix linting issues
Browse files Browse the repository at this point in the history
  • Loading branch information
nesmabadr committed Oct 31, 2024
1 parent 647d4c8 commit de9af96
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 117 deletions.
8 changes: 5 additions & 3 deletions api/v1alpha1/sample_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
// Package v1alpha1 contains API Schema definitions for the component v1alpha1 API group
// +kubebuilder:object:generate=true
// +groupName=operator.kyma-project.io
//
//nolint:gochecknoglobals // required for utilizing the API
package v1alpha1

import (
Expand Down Expand Up @@ -80,9 +82,9 @@ type SampleSpec struct {
ResourceFilePath string `json:"resourceFilePath,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="State",type=string,JSONPath=".status.state"
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="State",type=string,JSONPath=".status.state"

// Sample is the Schema for the samples API.
type Sample struct {
Expand Down
61 changes: 37 additions & 24 deletions controllers/sample_controller_rendered_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"os"
"path/filepath"

"sigs.k8s.io/controller-runtime/pkg/scheme"

"github.com/go-logr/logr"
errors2 "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -35,12 +33,12 @@ import (
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/scheme"

"github.com/kyma-project/template-operator/api/v1alpha1"

"sigs.k8s.io/controller-runtime/pkg/controller"
)

// SampleReconciler reconciles a Sample object.
Expand All @@ -61,13 +59,15 @@ type ManifestResources struct {

var (
// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
//nolint:gochecknoglobals // used to register Sample CRD on startup
SchemeBuilder = &scheme.Builder{GroupVersion: v1alpha1.GroupVersion}

// AddToScheme adds the types in this group-version to the given scheme.
//nolint:gochecknoglobals // used to register Sample CRD on startup
AddToScheme = SchemeBuilder.AddToScheme
)

func init() { //nolint:gochecknoinits
func init() { //nolint:gochecknoinits // used to register Sample CRD on startup
SchemeBuilder.Register(&v1alpha1.Sample{}, &v1alpha1.SampleList{})
}

Expand All @@ -84,7 +84,7 @@ func init() { //nolint:gochecknoinits
func (r *SampleReconciler) SetupWithManager(mgr ctrl.Manager, rateLimiter RateLimiter) error {
r.Config = mgr.GetConfig()

return ctrl.NewControllerManagedBy(mgr).
if err := ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.Sample{}).
WithOptions(controller.Options{
RateLimiter: TemplateRateLimiter(
Expand All @@ -94,7 +94,10 @@ func (r *SampleReconciler) SetupWithManager(mgr ctrl.Manager, rateLimiter RateLi
rateLimiter.Burst,
),
}).
Complete(r)
Complete(r); err != nil {
return fmt.Errorf("error while setting up controller: %w", err)
}
return nil
}

// Reconcile is the entry point from the controller-runtime framework.
Expand All @@ -104,12 +107,12 @@ func (r *SampleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr

objectInstance := v1alpha1.Sample{}

if err := r.Client.Get(ctx, req.NamespacedName, &objectInstance); err != nil {
if err := r.Client.Get(ctx, req.NamespacedName, &objectInstance); client.IgnoreNotFound(err) != nil {
// we'll ignore not-found errors, since they can't be fixed by an immediate
// requeue (we'll need to wait for a new notification), and we can get them
// on deleted requests.
logger.Info(req.NamespacedName.String() + " got deleted!")
return ctrl.Result{}, client.IgnoreNotFound(err)
return ctrl.Result{}, fmt.Errorf("error while getting object: %w", err)
}

// check if deletionTimestamp is set, retry until it gets deleted
Expand Down Expand Up @@ -201,7 +204,9 @@ func (r *SampleReconciler) HandleDeletingState(ctx context.Context, objectInstan
resourceObjs, err := getResourcesFromLocalPath(objectInstance.Spec.ResourceFilePath, logger)
if err != nil && controllerutil.RemoveFinalizer(objectInstance, finalizer) {
// if error is encountered simply remove the finalizer and delete the reconciled resource
return r.Client.Update(ctx, objectInstance)
if err := r.Client.Update(ctx, objectInstance); err != nil {
return fmt.Errorf("error while removing finalizer: %w", err)
}
}
r.Event(objectInstance, "Normal", "ResourcesDelete", "deleting resources")

Expand All @@ -224,7 +229,9 @@ func (r *SampleReconciler) HandleDeletingState(ctx context.Context, objectInstan

// if resources are ready to be deleted, remove finalizer
if controllerutil.RemoveFinalizer(objectInstance, finalizer) {
return r.Client.Update(ctx, objectInstance)
if err := r.Client.Update(ctx, objectInstance); err != nil {
return fmt.Errorf("error while removing finalizer: %w", err)
}
}
return nil
}
Expand Down Expand Up @@ -268,7 +275,7 @@ func (r *SampleReconciler) processResources(ctx context.Context, objectInstance
resourceObjs, err := getResourcesFromLocalPath(objectInstance.Spec.ResourceFilePath, logger)
if err != nil {
logger.Error(err, "error locating manifest of resources")
return err
return fmt.Errorf("error locating manifest of resources: %w", err)
}

r.Event(objectInstance, "Normal", "ResourcesInstall", "installing resources")
Expand All @@ -278,7 +285,7 @@ func (r *SampleReconciler) processResources(ctx context.Context, objectInstance
for _, obj := range resourceObjs.Items {
if err = r.ssa(ctx, obj); err != nil && !errors2.IsAlreadyExists(err) {
logger.Error(err, "error during installation of resources")
return err
return fmt.Errorf("error during installation of resources: %w", err)
}
}
return nil
Expand All @@ -295,30 +302,30 @@ func getResourcesFromLocalPath(dirPath string, logger logr.Logger) (*ManifestRes
err := filepath.WalkDir(dirPath, func(path string, info fs.DirEntry, err error) error {
// initial error
if err != nil {
return err
return fmt.Errorf("error while walkdir %s: %w", dirPath, err)
}
if !info.IsDir() {
return nil
}
dirEntries, err = os.ReadDir(dirPath)
return err
return fmt.Errorf("error while reading directory %s: %w", dirPath, err)
})
if err != nil {
return nil, err
return nil, fmt.Errorf("error while walkdir %s: %w", dirPath, err)
}

childCount := len(dirEntries)
if childCount == 0 {
logger.V(debugLogLevel).Info(fmt.Sprintf("no yaml file found at file path %s", dirPath))
return nil, nil
logger.V(debugLogLevel).Info("no yaml file found at file path" + dirPath)
return nil, nil //nolint:nilnil // nil is returned if no yaml file is found
} else if childCount > 1 {
logger.V(debugLogLevel).Info(fmt.Sprintf("more than one yaml file found at file path %s", dirPath))
return nil, nil
logger.V(debugLogLevel).Info("more than one yaml file found at file path" + dirPath)
return nil, nil //nolint:nilnil // nil is returned if more than one yaml file is found
}
file := dirEntries[0]
allowedExtns := sets.NewString(".yaml", ".yml")
if !allowedExtns.Has(filepath.Ext(file.Name())) {
return nil, nil
return nil, nil //nolint:nilnil // nil is returned if file is not in yaml format
}

fileBytes, err := os.ReadFile(filepath.Join(dirPath, file.Name()))
Expand All @@ -332,13 +339,19 @@ func getResourcesFromLocalPath(dirPath string, logger logr.Logger) (*ManifestRes
func (r *SampleReconciler) ssaStatus(ctx context.Context, obj client.Object) error {
obj.SetManagedFields(nil)
obj.SetResourceVersion("")
return r.Status().Patch(ctx, obj, client.Apply,
&client.SubResourcePatchOptions{PatchOptions: client.PatchOptions{FieldManager: fieldOwner}})
if err := r.Status().Patch(ctx, obj, client.Apply,
&client.SubResourcePatchOptions{PatchOptions: client.PatchOptions{FieldManager: fieldOwner}}); err != nil {
return fmt.Errorf("error while patching status: %w", err)
}
return nil
}

// ssa patches the object using SSA.
func (r *SampleReconciler) ssa(ctx context.Context, obj client.Object) error {
obj.SetManagedFields(nil)
obj.SetResourceVersion("")
return r.Patch(ctx, obj, client.Apply, client.ForceOwnership, client.FieldOwner(fieldOwner))
if err := r.Patch(ctx, obj, client.Apply, client.ForceOwnership, client.FieldOwner(fieldOwner)); err != nil {
return fmt.Errorf("error while patching object: %w", err)
}
return nil
}
114 changes: 57 additions & 57 deletions controllers/sample_controller_rendered_resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/kyma-project/template-operator/api/v1alpha1"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

var (
Expand All @@ -28,12 +28,14 @@ var _ = Describe("Sample CR is created with the correct resource path", Ordered,
It("should create SampleCR and resources", func() {
Expect(k8sClient.Create(ctx, sampleCR)).To(Succeed())

Eventually(getCRStatus(sampleCRKey)).
Eventually(getCRStatus).
WithArguments(sampleCRKey).
WithTimeout(30 * time.Second).
WithPolling(500 * time.Millisecond).
Should(Equal(CRStatus{State: v1alpha1.StateReady, InstallConditionStatus: metav1.ConditionTrue, Err: nil}))

Eventually(getPod(podNs, podName)).
Eventually(getPod).
WithArguments(podNs, podName).
WithTimeout(30 * time.Second).
WithPolling(500 * time.Millisecond).
Should(BeTrue())
Expand All @@ -43,14 +45,16 @@ var _ = Describe("Sample CR is created with the correct resource path", Ordered,
reconciler.FinalDeletionState = v1alpha1.StateWarning
Expect(k8sClient.Delete(ctx, sampleCR)).To(Succeed())

Eventually(getCRStatus(sampleCRKey)).
Eventually(getCRStatus).
WithArguments(sampleCRKey).
WithTimeout(30 * time.Second).
WithPolling(500 * time.Millisecond).
Should(Equal(CRStatus{
State: v1alpha1.StateWarning,
InstallConditionStatus: metav1.ConditionTrue, Err: nil,
}))
Consistently(getCRStatus(sampleCRKey)).
Consistently(getCRStatus).
WithArguments(sampleCRKey).
WithTimeout(5 * time.Second).
WithPolling(100 * time.Millisecond).
Should(Equal(CRStatus{
Expand All @@ -61,7 +65,8 @@ var _ = Describe("Sample CR is created with the correct resource path", Ordered,

It("should delete when FinalDeletionState set to Deleting", func() {
reconciler.FinalDeletionState = v1alpha1.StateDeleting
Eventually(checkDeleted(sampleCRKey)).
Eventually(checkDeleted).
WithArguments(sampleCRKey).
WithTimeout(30 * time.Second).
WithPolling(500 * time.Millisecond).
Should(BeTrue())
Expand All @@ -74,7 +79,8 @@ var _ = Describe("Sample CR is created with an incorrect resource path", Ordered

It("should create SampleCR in Error state", func() {
Expect(k8sClient.Create(ctx, sampleCR)).To(Succeed())
Eventually(getCRStatus(sampleCRKey)).
Eventually(getCRStatus).
WithArguments(sampleCRKey).
WithTimeout(30 * time.Second).
WithPolling(500 * time.Millisecond).
Should(Equal(CRStatus{State: v1alpha1.StateError, InstallConditionStatus: metav1.ConditionFalse, Err: nil}))
Expand All @@ -97,27 +103,25 @@ func createSampleCR(sampleName, path string) *v1alpha1.Sample {
}
}

func getPod(namespace, podName string) func(g Gomega) bool {
return func(g Gomega) bool {
clientSet, err := kubernetes.NewForConfig(reconciler.Config)
g.Expect(err).ToNot(HaveOccurred())

pod, err := clientSet.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
if err != nil {
return false
}

// Because there are no controllers monitoring built-in resources, state of objects do not get updated.
// Thus, 'Ready'-State of pod needs to be set manually.
pod.Status.Conditions = append(pod.Status.Conditions, v1.PodCondition{
Type: v1.PodReady,
Status: v1.ConditionTrue,
})

_, err = clientSet.CoreV1().Pods(namespace).UpdateStatus(ctx, pod, metav1.UpdateOptions{})
g.Expect(err).ToNot(HaveOccurred())
return true
func getPod(namespace, podName string) bool {
clientSet, err := kubernetes.NewForConfig(reconciler.Config)
Expect(err).ToNot(HaveOccurred())

pod, err := clientSet.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
if err != nil {
return false
}

// Because there are no controllers monitoring built-in resources, state of objects do not get updated.
// Thus, 'Ready'-State of pod needs to be set manually.
pod.Status.Conditions = append(pod.Status.Conditions, v1.PodCondition{
Type: v1.PodReady,
Status: v1.ConditionTrue,
})

_, err = clientSet.CoreV1().Pods(namespace).UpdateStatus(ctx, pod, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
return true
}

type CRStatus struct {
Expand All @@ -126,37 +130,33 @@ type CRStatus struct {
Err error
}

func getCRStatus(sampleObjKey client.ObjectKey) func(g Gomega) CRStatus {
return func(g Gomega) CRStatus {
sampleCR := &v1alpha1.Sample{}
err := k8sClient.Get(ctx, sampleObjKey, sampleCR)
if err != nil {
return CRStatus{State: v1alpha1.StateError, Err: err}
}
g.Expect(err).NotTo(HaveOccurred())
condition := meta.FindStatusCondition(sampleCR.Status.Conditions, v1alpha1.ConditionTypeInstallation)
g.Expect(condition).ShouldNot(BeNil())
return CRStatus{
State: sampleCR.Status.State,
InstallConditionStatus: condition.Status,
Err: nil,
}
func getCRStatus(sampleObjKey client.ObjectKey) CRStatus {
sampleCR := &v1alpha1.Sample{}
err := k8sClient.Get(ctx, sampleObjKey, sampleCR)
if err != nil {
return CRStatus{State: v1alpha1.StateError, Err: err}
}
Expect(err).NotTo(HaveOccurred())
condition := meta.FindStatusCondition(sampleCR.Status.Conditions, v1alpha1.ConditionTypeInstallation)
Expect(condition).ShouldNot(BeNil())
return CRStatus{
State: sampleCR.Status.State,
InstallConditionStatus: condition.Status,
Err: nil,
}
}

func checkDeleted(sampleObjKey client.ObjectKey) func(g Gomega) bool {
return func(g Gomega) bool {
clientSet, err := kubernetes.NewForConfig(reconciler.Config)
g.Expect(err).ToNot(HaveOccurred())

// check if Pod resource is deleted
_, err = clientSet.CoreV1().Pods(podNs).Get(ctx, podName, metav1.GetOptions{})
if errors.IsNotFound(err) {
sampleCR := v1alpha1.Sample{}
// check if reconciled resource is also deleted
err = k8sClient.Get(ctx, sampleObjKey, &sampleCR)
return errors.IsNotFound(err)
}
return false
func checkDeleted(sampleObjKey client.ObjectKey) bool {
clientSet, err := kubernetes.NewForConfig(reconciler.Config)
Expect(err).ToNot(HaveOccurred())

// check if Pod resource is deleted
_, err = clientSet.CoreV1().Pods(podNs).Get(ctx, podName, metav1.GetOptions{})
if errors.IsNotFound(err) {
sampleCR := v1alpha1.Sample{}
// check if reconciled resource is also deleted
err = k8sClient.Get(ctx, sampleObjKey, &sampleCR)
return errors.IsNotFound(err)
}
return false
}
Loading

0 comments on commit de9af96

Please sign in to comment.