1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/pkg/webhooks/resource/utils.go
Charles-Edouard Brétéché 02e27ec3d4
fix: unsupported defaults in api (#11021)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2024-09-05 14:48:47 +00:00

122 lines
4 KiB
Go

package resource
import (
"context"
"errors"
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
"github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/types"
)
type updateRequestResponse struct {
ur kyvernov2.UpdateRequestSpec
err error
}
func errorResponse(logger logr.Logger, uid types.UID, err error, message string) admissionv1.AdmissionResponse {
logger.Error(err, message)
return admissionutils.Response(uid, errors.New(message+": "+err.Error()))
}
func patchRequest(patches []byte, request admissionv1.AdmissionRequest, logger logr.Logger) admissionv1.AdmissionRequest {
patchedResource := processResourceWithPatches(patches, request.Object.Raw, logger)
request.Object.Raw = patchedResource
return request
}
func processResourceWithPatches(patch []byte, resource []byte, log logr.Logger) []byte {
if patch == nil {
return resource
}
resource, err := engineutils.ApplyPatchNew(resource, patch)
if err != nil {
log.Error(err, "failed to patch resource:", "patch", string(patch), "resource", string(resource))
return nil
}
log.V(6).Info("", "patchedResource", string(resource))
return resource
}
func applyUpdateRequest(
ctx context.Context,
request admissionv1.AdmissionRequest,
ruleType kyvernov2.RequestType,
urGenerator updaterequest.Generator,
userRequestInfo kyvernov2.RequestInfo,
action admissionv1.Operation,
engineResponses ...*engineapi.EngineResponse,
) (failedUpdateRequest []updateRequestResponse) {
admissionRequestInfo := kyvernov2.AdmissionRequestInfoObject{
AdmissionRequest: &request,
Operation: action,
}
for _, er := range engineResponses {
urs := transform(admissionRequestInfo, userRequestInfo, er, ruleType)
for _, ur := range urs {
if err := urGenerator.Apply(ctx, ur); err != nil {
failedUpdateRequest = append(failedUpdateRequest, updateRequestResponse{ur: ur, err: err})
}
}
}
return
}
func transform(admissionRequestInfo kyvernov2.AdmissionRequestInfoObject, userRequestInfo kyvernov2.RequestInfo, er *engineapi.EngineResponse, ruleType kyvernov2.RequestType) (urs []kyvernov2.UpdateRequestSpec) {
var PolicyNameNamespaceKey string
if er.Policy().GetNamespace() != "" {
PolicyNameNamespaceKey = er.Policy().GetNamespace() + "/" + er.Policy().GetName()
} else {
PolicyNameNamespaceKey = er.Policy().GetName()
}
for _, rule := range er.PolicyResponse.Rules {
ur := kyvernov2.UpdateRequestSpec{
Type: ruleType,
Policy: PolicyNameNamespaceKey,
Rule: rule.Name(),
Resource: kyvernov1.ResourceSpec{
Kind: er.Resource.GetKind(),
Namespace: er.Resource.GetNamespace(),
Name: er.Resource.GetName(),
APIVersion: er.Resource.GetAPIVersion(),
UID: er.Resource.GetUID(),
},
Context: kyvernov2.UpdateRequestSpecContext{
UserRequestInfo: userRequestInfo,
AdmissionRequestInfo: admissionRequestInfo,
},
}
urs = append(urs, ur)
}
return urs
}
func skipBackgroundRequests(policy kyvernov1.PolicyInterface, logger logr.Logger, bgsaDesired, bgsaActual string) kyvernov1.PolicyInterface {
policyNew := policy.CreateDeepCopy()
policyNew.GetSpec().Rules = nil
for _, rule := range policy.GetSpec().Rules {
skipBackgroundRequests := true
if rule.SkipBackgroundRequests != nil {
skipBackgroundRequests = *rule.SkipBackgroundRequests
}
if skipBackgroundRequests && (bgsaDesired == bgsaActual) {
continue
}
logger.V(4).Info("applying background rule", "rule", rule.Name, "skipBackgroundRequests", rule.SkipBackgroundRequests, "backgroundSaDesired", bgsaDesired, "backgroundSaActual", bgsaActual)
policyNew.GetSpec().Rules = append(policyNew.GetSpec().Rules, *rule.DeepCopy())
}
if len(policyNew.GetSpec().Rules) == 0 {
return nil
}
return policyNew
}