opdev / opcap

Apache License 2.0
3 stars 15 forks source link

ADD report data for failed InstallPlans #125

Open acmenezes opened 2 years ago

acmenezes commented 2 years ago

InstallPlan may contain information for tracing and debugging that can later be used for improving reporting on the tool.

acmenezes commented 2 years ago

Here is the old code that can be repurposed to get data from InstallPlan:

package operator

import (
    "context"
    "fmt"
    "time"

    operatorv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
    "k8s.io/apimachinery/pkg/types"
    "k8s.io/apimachinery/pkg/util/wait"
    runtimeClient "sigs.k8s.io/controller-runtime/pkg/client"
)

// ApproveInstallPlan waits and approves installPlans
func (c operatorClient) ApproveInstallPlan(ctx context.Context, sub *operatorv1alpha1.Subscription) error {
    subKey := types.NamespacedName{
        Namespace: sub.GetNamespace(),
        Name:      sub.GetName(),
    }

    ipCheck := wait.ConditionFunc(func() (done bool, err error) {
        if err := c.Client.Get(ctx, subKey, sub); err != nil {
            return false, err
        }
        if sub.Status.InstallPlanRef != nil {
            return true, nil
        }
        return false, nil
    })

    if err := wait.PollImmediateUntil(200*time.Millisecond, ipCheck, ctx.Done()); err != nil {
        logger.Errorf("install plan is not available for the subscription %s: %w", sub.Name, err)
        return fmt.Errorf("install plan is not available for the subscription %s: %v", sub.Name, err)
    }

    err := c.installPlanApprove(sub.ObjectMeta.Namespace)
    if err != nil {
        logger.Debugf("Error creating subscriptions: %w", err)
        return err
    }

    return nil
}

// InstallPlanApprove logic
// TODO: consolidate ApproveInstallPlan and InstallPlanApprove in a single and cleaner function
func (c operatorClient) installPlanApprove(namespace string) error {
    installPlanList := operatorv1alpha1.InstallPlanList{}

    listOpts := runtimeClient.ListOptions{
        Namespace: namespace,
    }

    err := c.Client.List(context.Background(), &installPlanList, &listOpts)
    if err != nil {
        logger.Errorf("Unable to list InstallPlans in Namespace %s: %w", namespace, err)
        return err
    }

    if len(installPlanList.Items) == 0 {
        logger.Errorf("no installPlan found in namespace %s: %w", namespace, err)
        return fmt.Errorf("no installPlan found in namespace %s", fmt.Sprint(len(installPlanList.Items)))
    }

    installPlan := operatorv1alpha1.InstallPlan{}

    err = c.Client.Get(context.Background(), types.NamespacedName{Name: installPlanList.Items[0].ObjectMeta.Name, Namespace: namespace}, &installPlan)

    if err != nil {
        logger.Errorf("no installPlan found in namespace %s: %w", namespace, err)
        return err
    }

    if installPlan.Spec.Approval == operatorv1alpha1.ApprovalManual {

        installPlan.Spec.Approved = true
        logger.Debugf("%s installPlan approved in Namespace %s", installPlan.ObjectMeta.Name, namespace)
        err := c.Client.Update(context.Background(), &installPlan)
        if err != nil {
            logger.Errorf("Error: %w", err)
            return err
        }
    }
    return nil
}
mgoerens commented 2 years ago

Also check the refactored version of the code above. Available here: https://github.com/opdev/opcap/blob/645e401e8ab7428895cfdc1f0b4efc9e8ace5f23/internal/operator/install_plan.go