1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/utils/util.go
Shuting Zhao a1eda94a80 Merge branch 'main' into policyreport
# Conflicts:
#	pkg/utils/util.go
2020-11-03 16:43:00 -08:00

185 lines
5.3 KiB
Go

package utils
import (
"fmt"
"reflect"
"regexp"
"strconv"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/go-logr/logr"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/minio/minio/pkg/wildcard"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
var regexVersion = regexp.MustCompile(`v(\d+).(\d+).(\d+)\.*`)
//Contains Check if strint is contained in a list of string
func contains(list []string, element string, fn func(string, string) bool) bool {
for _, e := range list {
if fn(e, element) {
return true
}
}
return false
}
//ContainsNamepace check if namespace satisfies any list of pattern(regex)
func ContainsNamepace(patterns []string, ns string) bool {
return contains(patterns, ns, compareNamespaces)
}
//ContainsString check if the string is contains in a list
func ContainsString(list []string, element string) bool {
return contains(list, element, compareString)
}
func compareNamespaces(pattern, ns string) bool {
return wildcard.Match(pattern, ns)
}
func compareString(str, name string) bool {
return str == name
}
//NewKubeClient returns a new kubernetes client
func NewKubeClient(config *rest.Config) (kubernetes.Interface, error) {
kclient, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return kclient, nil
}
//CRDInstalled to check if the CRD is installed or not
func CRDInstalled(discovery client.IDiscovery, log logr.Logger) bool {
logger := log.WithName("CRDInstalled")
check := func(kind string) bool {
gvr := discovery.GetGVRFromKind(kind)
if reflect.DeepEqual(gvr, schema.GroupVersionResource{}) {
logger.Info("CRD not installed", "kind", kind)
return false
}
logger.Info("CRD found", "kind", kind)
return true
}
kyvernoCRDs := []string{"ClusterPolicy", "ClusterPolicyReport", "PolicyReport", "ClusterReportChangeRequest", "ReportChangeRequest"}
for _, crd := range kyvernoCRDs {
if !check(crd) {
return false
}
}
return true
}
// extracts the new and old resource as unstructured
func ExtractResources(newRaw []byte, request *v1beta1.AdmissionRequest) (unstructured.Unstructured, unstructured.Unstructured, error) {
var emptyResource unstructured.Unstructured
var newResource unstructured.Unstructured
var oldResource unstructured.Unstructured
var err error
// New Resource
if newRaw == nil {
newRaw = request.Object.Raw
}
if newRaw != nil {
newResource, err = ConvertResource(newRaw, request.Kind.Group, request.Kind.Version, request.Kind.Kind, request.Namespace)
if err != nil {
return emptyResource, emptyResource, fmt.Errorf("failed to convert new raw to unstructured: %v", err)
}
}
// Old Resource
oldRaw := request.OldObject.Raw
if oldRaw != nil {
oldResource, err = ConvertResource(oldRaw, request.Kind.Group, request.Kind.Version, request.Kind.Kind, request.Namespace)
if err != nil {
return emptyResource, emptyResource, fmt.Errorf("failed to convert old raw to unstructured: %v", err)
}
}
return newResource, oldResource, err
}
// convertResource converts raw bytes to an unstructured object
func ConvertResource(raw []byte, group, version, kind, namespace string) (unstructured.Unstructured, error) {
obj, err := engineutils.ConvertToUnstructured(raw)
if err != nil {
return unstructured.Unstructured{}, fmt.Errorf("failed to convert raw to unstructured: %v", err)
}
obj.SetGroupVersionKind(schema.GroupVersionKind{Group: group, Version: version, Kind: kind})
obj.SetNamespace(namespace)
return *obj, nil
}
// HigherThanKubernetesVersion compare Kubernetes client version to user given version
func HigherThanKubernetesVersion(client *client.Client, log logr.Logger, major, minor, patch int) bool {
logger := log.WithName("CompareKubernetesVersion")
serverVersion, err := client.DiscoveryClient.GetServerVersion()
if err != nil {
logger.Error(err, "Failed to get kubernetes server version")
return false
}
b, err := isVersionHigher(serverVersion.String(), major, minor, patch)
if err != nil {
logger.Error(err, "serverVersion", serverVersion)
return false
}
return b
}
func isVersionHigher(version string, major int, minor int, patch int) (bool, error) {
groups := regexVersion.FindAllStringSubmatch(version, -1)
if len(groups) != 1 || len(groups[0]) != 4 {
return false, fmt.Errorf("invalid version %s. Expected {major}.{minor}.{patch}", version)
}
currentMajor, err := strconv.Atoi(groups[0][1])
if err != nil {
return false, fmt.Errorf("failed to extract major version from %s", version)
}
currentMinor, err := strconv.Atoi(groups[0][2])
if err != nil {
return false, fmt.Errorf("failed to extract minor version from %s", version)
}
currentPatch, err := strconv.Atoi(groups[0][3])
if err != nil {
return false, fmt.Errorf("failed to extract minor version from %s", version)
}
if currentMajor <= major && currentMinor <= minor && currentPatch <= patch {
return false, nil
}
return true, nil
}
func SliceContains(slice []string, values ...string) bool {
var sliceElementsMap = make(map[string]bool, len(slice))
for _, sliceElement := range slice {
sliceElementsMap[sliceElement] = true
}
for _, value := range values {
if sliceElementsMap[value] {
return true
}
}
return false
}