func()

in kubectl-utils/pkg/kel/info.go [68:147]


func (x *Expression) buildFunctionPrinterFor(args []*exprpb.Expr) (InfoFunction, error) {
	checkedExpr, err := cel.AstToCheckedExpr(x.AST)
	if err != nil {
		return nil, fmt.Errorf("parsing CEL ast: %w", err)
	}

	type debugValue struct {
		Key     string
		Program cel.Program
	}
	var debugValues []debugValue

	for _, arg := range args {
		shouldPrint := true

		v := arg.ExprKind
		switch v := v.(type) {
		case *exprpb.Expr_ConstExpr:
			// Don't print constants, 2=2 is not informative
			shouldPrint = false
		case *exprpb.Expr_SelectExpr:
			shouldPrint = true

		default:
			klog.Warningf("unhandled expression kind %T", v)
		}

		if !shouldPrint {
			continue
		}

		checkedArg := proto.Clone(checkedExpr).(*exprpb.CheckedExpr)
		checkedArg.Expr = arg

		ast := cel.CheckedExprToAst(checkedArg)
		celExpression, err := cel.AstToString(ast)
		if err != nil {
			return nil, fmt.Errorf("converting expression to string: %w", err)
		}

		compiled, issues := x.Env.Compile(celExpression)
		if issues != nil && issues.Err() != nil {
			return nil, fmt.Errorf("invalid expression %q: %w", celExpression, issues.Err())
		}
		prg, err := x.Env.Program(compiled)
		if err != nil {
			return nil, fmt.Errorf("invalid expression %q: %w", celExpression, err)
		}

		debugValues = append(debugValues, debugValue{
			Key:     celExpression,
			Program: prg,
		})
	}

	if len(debugValues) == 0 {
		return nil, nil
	}

	return func(ctx context.Context, self *unstructured.Unstructured) string {
		log := klog.FromContext(ctx)

		inputs := x.buildInputs(self)

		var values []string
		for _, debugValue := range debugValues {
			s := ""
			out, details, err := debugValue.Program.Eval(inputs)
			log.V(2).Info("evaluated CEL expression", "out", out, "details", details, "error", err)
			if err == nil {
				s = fmt.Sprintf("%s=%v", debugValue.Key, out.Value())
			} else {
				s = fmt.Sprintf("%s=%v", debugValue.Key, "???")
			}
			values = append(values, s)
		}

		return strings.Join(values, "; ")
	}, nil
}