package image import ( "github.com/google/cel-go/cel" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/go-containerregistry/pkg/name" ) const libraryName = "kyverno.image" func ImageLib() cel.EnvOption { return cel.Lib(imageLib) } var imageLib = &imageLibType{} type imageLibType struct{} func (*imageLibType) LibraryName() string { return libraryName } func (*imageLibType) Types() []*cel.Type { return []*cel.Type{ImageType} } func (*imageLibType) declarations() map[string][]cel.FunctionOpt { return map[string][]cel.FunctionOpt{ "image": { cel.Overload("string_to_image", []*cel.Type{cel.StringType}, ImageType, cel.UnaryBinding((stringToImage))), }, "isImage": { cel.Overload("is_image_string", []*cel.Type{cel.StringType}, cel.BoolType, cel.UnaryBinding(isImage)), }, "containsDigest": { cel.MemberOverload("image_contains_digest", []*cel.Type{ImageType}, cel.BoolType, cel.UnaryBinding(imageContainsDigest)), }, "registry": { cel.MemberOverload("image_registry", []*cel.Type{ImageType}, cel.StringType, cel.UnaryBinding(imageRegistry)), }, "repository": { cel.MemberOverload("image_repository", []*cel.Type{ImageType}, cel.StringType, cel.UnaryBinding(imageRepository)), }, "identifier": { cel.MemberOverload("image_identifier", []*cel.Type{ImageType}, cel.StringType, cel.UnaryBinding(imageIdentifier)), }, "tag": { cel.MemberOverload("image_tag", []*cel.Type{ImageType}, cel.StringType, cel.UnaryBinding(imageTag)), }, "digest": { cel.MemberOverload("image_digest", []*cel.Type{ImageType}, cel.StringType, cel.UnaryBinding(imageDigest)), }, } } func (i *imageLibType) CompileOptions() []cel.EnvOption { imageLibraryDecls := i.declarations() options := make([]cel.EnvOption, 0, len(imageLibraryDecls)) for name, overloads := range imageLibraryDecls { options = append(options, cel.Function(name, overloads...)) } return options } func (*imageLibType) ProgramOptions() []cel.ProgramOption { return []cel.ProgramOption{} } func isImage(arg ref.Val) ref.Val { str, ok := arg.Value().(string) if !ok { return types.MaybeNoSuchOverloadErr(arg) } _, err := name.ParseReference(str) if err != nil { return types.Bool(false) } return types.Bool(true) } func stringToImage(arg ref.Val) ref.Val { str, ok := arg.Value().(string) if !ok { return types.MaybeNoSuchOverloadErr(arg) } v, err := name.ParseReference(str) if err != nil { return types.WrapErr(err) } return Image{ImageReference: ConvertToImageRef(v)} } func imageContainsDigest(arg ref.Val) ref.Val { v, ok := arg.Value().(ImageReference) if !ok { return types.MaybeNoSuchOverloadErr(arg) } return types.Bool(len(v.Digest) != 0) } func imageRegistry(arg ref.Val) ref.Val { v, ok := arg.Value().(ImageReference) if !ok { return types.MaybeNoSuchOverloadErr(arg) } return types.String(v.Registry) } func imageRepository(arg ref.Val) ref.Val { v, ok := arg.Value().(ImageReference) if !ok { return types.MaybeNoSuchOverloadErr(arg) } return types.String(v.Repository) } func imageIdentifier(arg ref.Val) ref.Val { v, ok := arg.Value().(ImageReference) if !ok { return types.MaybeNoSuchOverloadErr(arg) } return types.String(v.Identifier) } func imageTag(arg ref.Val) ref.Val { v, ok := arg.Value().(ImageReference) if !ok { return types.MaybeNoSuchOverloadErr(arg) } return types.String(v.Tag) } func imageDigest(arg ref.Val) ref.Val { v, ok := arg.Value().(ImageReference) if !ok { return types.MaybeNoSuchOverloadErr(arg) } return types.String(v.Digest) } func ConvertToImageRef(ref name.Reference) ImageReference { var img ImageReference img.Image = ref.String() img.Registry = ref.Context().RegistryStr() img.Repository = ref.Context().RepositoryStr() img.Identifier = ref.Identifier() if _, ok := ref.(name.Tag); ok { img.Tag = ref.Identifier() } else { img.Digest = ref.Identifier() } return img }