Skip to content

Commit

Permalink
feat: support image policy
Browse files Browse the repository at this point in the history
Signed-off-by: HIHIA <[email protected]>
  • Loading branch information
YTGhost committed Jan 16, 2023
1 parent 91ba640 commit f6b3c32
Show file tree
Hide file tree
Showing 5,894 changed files with 1,610,031 additions and 131,787 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion cmd/sealer/cmd/cluster/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ func installApplication(appImageName string, envs []string, app *v2.Application,
return loadToRegistry(infraDriver, distributor)
}

installer := clusterruntime.NewAppInstaller(infraDriver, distributor, extension)
installer := clusterruntime.NewAppInstaller(infraDriver, distributor, extension, imageEngine)
err = installer.Install(infraDriver.GetHostIPListByRole(common.MASTER)[0], v2App.GetImageLaunchCmds())
if err != nil {
return err
Expand Down
64 changes: 64 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,70 @@ const (
WINDOWS = "windows"
)

const (
ImagePolicyTemplateYamlName = "image-policy-template.yaml"
ImagePolicyTemplate = `
apiVersion : kyverno.io/v1
kind: ClusterPolicy
metadata:
name: [[.name]]-redirect-registry
namespace: kube-system
spec:
background: false
rules:
- name: prepend-registry-containers
match:
resources:
kinds:
- Pod
preconditions:
all:
- key: "{{request.operation}}"
operator: In
value:
- CREATE
- UPDATE
mutate:
foreach:
- list: "request.object.spec.containers"
preconditions:
all:
- key: "{{element.image}}"
operator: AnyIn
value: [[.imageList]]
patchStrategicMerge:
spec:
containers:
- name: "{{ element.name }}"
image: "[[.registry]]/{{ images.containers.{{element.name}}.path}}:{{images.containers.{{element.name}}.tag}}"
- name: prepend-registry-initcontainers
match:
resources:
kinds:
- Pod
preconditions:
all:
- key: "{{request.operation}}"
operator: In
value:
- CREATE
- UPDATE
mutate:
foreach:
- list: "request.object.spec.initContainers"
preconditions:
all:
- key: "{{element.image}}"
operator: AnyIn
value: [[.imageList]]
patchStrategicMerge:
spec:
initContainers:
- name: "{{ element.name }}"
image: "[[.registry]]/{{ images.initContainers.{{element.name}}.path}}:{{images.initContainers.{{element.name}}.tag}}"
`
)

func GetSealerWorkDir() string {
return filepath.Join(GetHomeDir(), ".sealer")
}
Expand Down
295 changes: 232 additions & 63 deletions go.mod

Large diffs are not rendered by default.

2,228 changes: 2,147 additions & 81 deletions go.sum

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion pkg/cluster-runtime/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
containerruntime "github.com/sealerio/sealer/pkg/container-runtime"
v12 "github.com/sealerio/sealer/pkg/define/image/v1"
"github.com/sealerio/sealer/pkg/imagedistributor"
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/imagepolicy/kyverno"
"github.com/sealerio/sealer/pkg/infradriver"
"github.com/sealerio/sealer/pkg/registry"
"github.com/sirupsen/logrus"
Expand All @@ -36,13 +38,15 @@ type AppInstaller struct {
infraDriver infradriver.InfraDriver
distributor imagedistributor.Distributor
extension v12.ImageExtension
imageEngine imageengine.Interface
}

func NewAppInstaller(infraDriver infradriver.InfraDriver, distributor imagedistributor.Distributor, extension v12.ImageExtension) AppInstaller {
func NewAppInstaller(infraDriver infradriver.InfraDriver, distributor imagedistributor.Distributor, extension v12.ImageExtension, imageEngine imageengine.Interface) AppInstaller {
return AppInstaller{
infraDriver: infraDriver,
distributor: distributor,
extension: extension,
imageEngine: imageEngine,
}
}

Expand Down Expand Up @@ -90,6 +94,11 @@ func (i AppInstaller) Launch(master0 net.IP, launchCmds []string) error {
ex = shell.NewLex('\\')
)

imagePolicyEngine, err := kyverno.NewKyvernoImagePolicyEngine()
if err != nil {
return err
}

for _, value := range launchCmds {
if value == "" {
continue
Expand All @@ -102,6 +111,10 @@ func (i AppInstaller) Launch(master0 net.IP, launchCmds []string) error {
if err = i.infraDriver.CmdAsync(master0, fmt.Sprintf(common.CdAndExecCmd, rootfsPath, cmdline)); err != nil {
return err
}

if ok, err := imagePolicyEngine.IsImagePolicyApp(cmdline); err != nil && ok {
imagePolicyEngine.CreateImagePolicyRule(i.infraDriver, i.imageEngine, cmdline)
}
}

return i.save(common.GetDefaultApplicationFile())
Expand Down
2 changes: 1 addition & 1 deletion pkg/cluster-runtime/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func (i *Installer) Install() error {
return err
}

appInstaller := NewAppInstaller(i.infraDriver, i.Distributor, extension)
appInstaller := NewAppInstaller(i.infraDriver, i.Distributor, extension, i.ImageEngine)

v2App, err := application.NewV2Application(v2.ConstructApplication(i.Application, cmds, appNames), extension)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions pkg/imageengine/buildah/sealer_image_extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ func GetImageExtensionFromAnnotations(annotations map[string]string) (image_v1.I
return extension, nil
}

func (engine *Engine) GetSealerContainerImageList(opts *options.GetImageAnnoOptions) ([]*image_v1.ContainerImage, error) {
annotation, err := engine.GetImageAnnotation(opts)
var imageList []*image_v1.ContainerImage

result, err := GetContainerImagesFromAnnotations(annotation)
if err != nil {
return imageList, errors.Wrapf(err, "failed to get %s in image %s", image_v1.SealerImageContainerImageList, opts.ImageNameOrID)
}

return result, nil
}

func GetContainerImagesFromAnnotations(annotations map[string]string) ([]*image_v1.ContainerImage, error) {
var containerImageList []*image_v1.ContainerImage
annotationStr := annotations[image_v1.SealerImageContainerImageList]
Expand Down
2 changes: 2 additions & 0 deletions pkg/imageengine/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ type Interface interface {

GetSealerImageExtension(opts *options.GetImageAnnoOptions) (v1.ImageExtension, error)

GetSealerContainerImageList(opts *options.GetImageAnnoOptions) ([]*v1.ContainerImage, error)

LookupManifest(name string) (*libimage.ManifestList, error)

CreateManifest(name string, opts *options.ManifestCreateOpts) error
Expand Down
7 changes: 7 additions & 0 deletions pkg/imagepolicy/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package imagepolicy

import "github.com/sealerio/sealer/pkg/imagepolicy/kyverno"

func NewImagePolicyEngine() (Interface, error) {
return kyverno.NewKyvernoImagePolicyEngine()
}
12 changes: 12 additions & 0 deletions pkg/imagepolicy/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package imagepolicy

import (
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/infradriver"
)

type Interface interface {
IsImagePolicyApp(appName string) (bool, error)

CreateImagePolicyRule(infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface, appName string) error
}
91 changes: 91 additions & 0 deletions pkg/imagepolicy/kyverno/engine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package kyverno

import (
"context"
"fmt"
"io/ioutil"
"os"
"strings"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/serializer"
runtimeClient "sigs.k8s.io/controller-runtime/pkg/client"

kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/sealerio/sealer/common"
imagecommon "github.com/sealerio/sealer/pkg/define/options"
"github.com/sealerio/sealer/pkg/imageengine"
"github.com/sealerio/sealer/pkg/infradriver"
k "github.com/sealerio/sealer/pkg/runtime/kubernetes"
apimachineryRuntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
)

type Engine struct {
}

func NewKyvernoImagePolicyEngine() (*Engine, error) {
return &Engine{}, nil
}

func (engine *Engine) IsImagePolicyApp(appName string) (bool, error) {
return appName == "kyverno", nil
}

func (engine *Engine) CreateImagePolicyRule(infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface, appName string) error {
driver, err := k.NewKubeDriver(k.AdminKubeConfPath)
if err != nil {
return err
}

imagePolicyTemplateStr := common.ImagePolicyTemplate
templatePath := fmt.Sprintf("%s/application/apps/%s/%s", infraDriver.GetClusterRootfsPath(), appName, common.ImagePolicyTemplateYamlName)
if _, err := os.Stat(templatePath); err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
yamlFile, err := ioutil.ReadFile(templatePath)
if err != nil {
return err
}
imagePolicyTemplateStr = string(yamlFile)
}

clusterImageName := infraDriver.GetClusterImageName()
imageList, err := imageEngine.GetSealerContainerImageList(&imagecommon.GetImageAnnoOptions{ImageNameOrID: clusterImageName})
clusterPolicy := &kyvernov1.ClusterPolicy{}

var imageListArray []string
for _, containerImage := range imageList {
imageListArray = append(imageListArray, "\""+containerImage.Image+"\"")
}

ctx := map[string]string{
"name": clusterImageName,
"imageList": "[" + strings.Join(imageListArray, ",") + "]",
"registry": infraDriver.GetClusterRegistry().LocalRegistry.Domain,
}
imagePolicyTemplate, err := SubsituteTemplate(imagePolicyTemplateStr, ctx)
if err != nil {
return err
}

kyvernov1.AddToScheme(scheme.Scheme)
decoder := serializer.NewCodecFactory(scheme.Scheme).UniversalDecoder()
err = apimachineryRuntime.DecodeInto(decoder, []byte(imagePolicyTemplate), clusterPolicy)
if err != nil {
return err
}

if err := driver.Create(context.Background(), clusterPolicy, &runtimeClient.CreateOptions{}); err != nil {
if !apierrors.IsAlreadyExists(err) {
return fmt.Errorf("unable to create image policy: %v", err)
}

if err := driver.Update(context.Background(), clusterPolicy, &runtimeClient.UpdateOptions{}); err != nil {
return fmt.Errorf("unable to update image policy: %v", err)
}
}
return nil
}
21 changes: 21 additions & 0 deletions pkg/imagepolicy/kyverno/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package kyverno

import (
"bytes"
"text/template"
)

// SubsituteTemplate fills out the templates based on the context
func SubsituteTemplate(tmpl string, context interface{}) (string, error) {
// Use [[]] as identifier to avoid conflicts
t, tmplPrsErr := template.New("test").Delims("[[", "]]").Option("missingkey=zero").Parse(tmpl)
if tmplPrsErr != nil {
return "", tmplPrsErr
}
writer := bytes.NewBuffer([]byte{})
if err := t.Execute(writer, context); nil != err {
return "", err
}

return writer.String(), nil
}
27 changes: 27 additions & 0 deletions vendor/bitbucket.org/creachadair/shell/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions vendor/bitbucket.org/creachadair/shell/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions vendor/bitbucket.org/creachadair/shell/bitbucket-pipelines.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f6b3c32

Please sign in to comment.