Skip to content

Commit f6b3c32

Browse files
committed
feat: support image policy
Signed-off-by: HIHIA <[email protected]>
1 parent 91ba640 commit f6b3c32

File tree

5,894 files changed

+1610031
-131787
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

5,894 files changed

+1610031
-131787
lines changed

Diff for: cmd/sealer/cmd/cluster/run.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ func installApplication(appImageName string, envs []string, app *v2.Application,
392392
return loadToRegistry(infraDriver, distributor)
393393
}
394394

395-
installer := clusterruntime.NewAppInstaller(infraDriver, distributor, extension)
395+
installer := clusterruntime.NewAppInstaller(infraDriver, distributor, extension, imageEngine)
396396
err = installer.Install(infraDriver.GetHostIPListByRole(common.MASTER)[0], v2App.GetImageLaunchCmds())
397397
if err != nil {
398398
return err

Diff for: common/common.go

+64
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,70 @@ const (
127127
WINDOWS = "windows"
128128
)
129129

130+
const (
131+
ImagePolicyTemplateYamlName = "image-policy-template.yaml"
132+
ImagePolicyTemplate = `
133+
apiVersion : kyverno.io/v1
134+
kind: ClusterPolicy
135+
metadata:
136+
name: [[.name]]-redirect-registry
137+
namespace: kube-system
138+
spec:
139+
background: false
140+
rules:
141+
- name: prepend-registry-containers
142+
match:
143+
resources:
144+
kinds:
145+
- Pod
146+
preconditions:
147+
all:
148+
- key: "{{request.operation}}"
149+
operator: In
150+
value:
151+
- CREATE
152+
- UPDATE
153+
mutate:
154+
foreach:
155+
- list: "request.object.spec.containers"
156+
preconditions:
157+
all:
158+
- key: "{{element.image}}"
159+
operator: AnyIn
160+
value: [[.imageList]]
161+
patchStrategicMerge:
162+
spec:
163+
containers:
164+
- name: "{{ element.name }}"
165+
image: "[[.registry]]/{{ images.containers.{{element.name}}.path}}:{{images.containers.{{element.name}}.tag}}"
166+
- name: prepend-registry-initcontainers
167+
match:
168+
resources:
169+
kinds:
170+
- Pod
171+
preconditions:
172+
all:
173+
- key: "{{request.operation}}"
174+
operator: In
175+
value:
176+
- CREATE
177+
- UPDATE
178+
mutate:
179+
foreach:
180+
- list: "request.object.spec.initContainers"
181+
preconditions:
182+
all:
183+
- key: "{{element.image}}"
184+
operator: AnyIn
185+
value: [[.imageList]]
186+
patchStrategicMerge:
187+
spec:
188+
initContainers:
189+
- name: "{{ element.name }}"
190+
image: "[[.registry]]/{{ images.initContainers.{{element.name}}.path}}:{{images.initContainers.{{element.name}}.tag}}"
191+
`
192+
)
193+
130194
func GetSealerWorkDir() string {
131195
return filepath.Join(GetHomeDir(), ".sealer")
132196
}

Diff for: go.mod

+232-63
Large diffs are not rendered by default.

Diff for: go.sum

+2,147-81
Large diffs are not rendered by default.

Diff for: pkg/cluster-runtime/apps.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
containerruntime "github.com/sealerio/sealer/pkg/container-runtime"
2828
v12 "github.com/sealerio/sealer/pkg/define/image/v1"
2929
"github.com/sealerio/sealer/pkg/imagedistributor"
30+
"github.com/sealerio/sealer/pkg/imageengine"
31+
"github.com/sealerio/sealer/pkg/imagepolicy/kyverno"
3032
"github.com/sealerio/sealer/pkg/infradriver"
3133
"github.com/sealerio/sealer/pkg/registry"
3234
"github.com/sirupsen/logrus"
@@ -36,13 +38,15 @@ type AppInstaller struct {
3638
infraDriver infradriver.InfraDriver
3739
distributor imagedistributor.Distributor
3840
extension v12.ImageExtension
41+
imageEngine imageengine.Interface
3942
}
4043

41-
func NewAppInstaller(infraDriver infradriver.InfraDriver, distributor imagedistributor.Distributor, extension v12.ImageExtension) AppInstaller {
44+
func NewAppInstaller(infraDriver infradriver.InfraDriver, distributor imagedistributor.Distributor, extension v12.ImageExtension, imageEngine imageengine.Interface) AppInstaller {
4245
return AppInstaller{
4346
infraDriver: infraDriver,
4447
distributor: distributor,
4548
extension: extension,
49+
imageEngine: imageEngine,
4650
}
4751
}
4852

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

97+
imagePolicyEngine, err := kyverno.NewKyvernoImagePolicyEngine()
98+
if err != nil {
99+
return err
100+
}
101+
93102
for _, value := range launchCmds {
94103
if value == "" {
95104
continue
@@ -102,6 +111,10 @@ func (i AppInstaller) Launch(master0 net.IP, launchCmds []string) error {
102111
if err = i.infraDriver.CmdAsync(master0, fmt.Sprintf(common.CdAndExecCmd, rootfsPath, cmdline)); err != nil {
103112
return err
104113
}
114+
115+
if ok, err := imagePolicyEngine.IsImagePolicyApp(cmdline); err != nil && ok {
116+
imagePolicyEngine.CreateImagePolicyRule(i.infraDriver, i.imageEngine, cmdline)
117+
}
105118
}
106119

107120
return i.save(common.GetDefaultApplicationFile())

Diff for: pkg/cluster-runtime/installer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ func (i *Installer) Install() error {
202202
return err
203203
}
204204

205-
appInstaller := NewAppInstaller(i.infraDriver, i.Distributor, extension)
205+
appInstaller := NewAppInstaller(i.infraDriver, i.Distributor, extension, i.ImageEngine)
206206

207207
v2App, err := application.NewV2Application(v2.ConstructApplication(i.Application, cmds, appNames), extension)
208208
if err != nil {

Diff for: pkg/imageengine/buildah/sealer_image_extension.go

+12
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ func GetImageExtensionFromAnnotations(annotations map[string]string) (image_v1.I
5151
return extension, nil
5252
}
5353

54+
func (engine *Engine) GetSealerContainerImageList(opts *options.GetImageAnnoOptions) ([]*image_v1.ContainerImage, error) {
55+
annotation, err := engine.GetImageAnnotation(opts)
56+
var imageList []*image_v1.ContainerImage
57+
58+
result, err := GetContainerImagesFromAnnotations(annotation)
59+
if err != nil {
60+
return imageList, errors.Wrapf(err, "failed to get %s in image %s", image_v1.SealerImageContainerImageList, opts.ImageNameOrID)
61+
}
62+
63+
return result, nil
64+
}
65+
5466
func GetContainerImagesFromAnnotations(annotations map[string]string) ([]*image_v1.ContainerImage, error) {
5567
var containerImageList []*image_v1.ContainerImage
5668
annotationStr := annotations[image_v1.SealerImageContainerImageList]

Diff for: pkg/imageengine/interface.go

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ type Interface interface {
6161

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

64+
GetSealerContainerImageList(opts *options.GetImageAnnoOptions) ([]*v1.ContainerImage, error)
65+
6466
LookupManifest(name string) (*libimage.ManifestList, error)
6567

6668
CreateManifest(name string, opts *options.ManifestCreateOpts) error

Diff for: pkg/imagepolicy/common.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package imagepolicy
2+
3+
import "github.com/sealerio/sealer/pkg/imagepolicy/kyverno"
4+
5+
func NewImagePolicyEngine() (Interface, error) {
6+
return kyverno.NewKyvernoImagePolicyEngine()
7+
}

Diff for: pkg/imagepolicy/interface.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package imagepolicy
2+
3+
import (
4+
"github.com/sealerio/sealer/pkg/imageengine"
5+
"github.com/sealerio/sealer/pkg/infradriver"
6+
)
7+
8+
type Interface interface {
9+
IsImagePolicyApp(appName string) (bool, error)
10+
11+
CreateImagePolicyRule(infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface, appName string) error
12+
}

Diff for: pkg/imagepolicy/kyverno/engine.go

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package kyverno
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"strings"
9+
10+
apierrors "k8s.io/apimachinery/pkg/api/errors"
11+
"k8s.io/apimachinery/pkg/runtime/serializer"
12+
runtimeClient "sigs.k8s.io/controller-runtime/pkg/client"
13+
14+
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
15+
"github.com/sealerio/sealer/common"
16+
imagecommon "github.com/sealerio/sealer/pkg/define/options"
17+
"github.com/sealerio/sealer/pkg/imageengine"
18+
"github.com/sealerio/sealer/pkg/infradriver"
19+
k "github.com/sealerio/sealer/pkg/runtime/kubernetes"
20+
apimachineryRuntime "k8s.io/apimachinery/pkg/runtime"
21+
"k8s.io/client-go/kubernetes/scheme"
22+
)
23+
24+
type Engine struct {
25+
}
26+
27+
func NewKyvernoImagePolicyEngine() (*Engine, error) {
28+
return &Engine{}, nil
29+
}
30+
31+
func (engine *Engine) IsImagePolicyApp(appName string) (bool, error) {
32+
return appName == "kyverno", nil
33+
}
34+
35+
func (engine *Engine) CreateImagePolicyRule(infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface, appName string) error {
36+
driver, err := k.NewKubeDriver(k.AdminKubeConfPath)
37+
if err != nil {
38+
return err
39+
}
40+
41+
imagePolicyTemplateStr := common.ImagePolicyTemplate
42+
templatePath := fmt.Sprintf("%s/application/apps/%s/%s", infraDriver.GetClusterRootfsPath(), appName, common.ImagePolicyTemplateYamlName)
43+
if _, err := os.Stat(templatePath); err != nil {
44+
if !os.IsNotExist(err) {
45+
return err
46+
}
47+
} else {
48+
yamlFile, err := ioutil.ReadFile(templatePath)
49+
if err != nil {
50+
return err
51+
}
52+
imagePolicyTemplateStr = string(yamlFile)
53+
}
54+
55+
clusterImageName := infraDriver.GetClusterImageName()
56+
imageList, err := imageEngine.GetSealerContainerImageList(&imagecommon.GetImageAnnoOptions{ImageNameOrID: clusterImageName})
57+
clusterPolicy := &kyvernov1.ClusterPolicy{}
58+
59+
var imageListArray []string
60+
for _, containerImage := range imageList {
61+
imageListArray = append(imageListArray, "\""+containerImage.Image+"\"")
62+
}
63+
64+
ctx := map[string]string{
65+
"name": clusterImageName,
66+
"imageList": "[" + strings.Join(imageListArray, ",") + "]",
67+
"registry": infraDriver.GetClusterRegistry().LocalRegistry.Domain,
68+
}
69+
imagePolicyTemplate, err := SubsituteTemplate(imagePolicyTemplateStr, ctx)
70+
if err != nil {
71+
return err
72+
}
73+
74+
kyvernov1.AddToScheme(scheme.Scheme)
75+
decoder := serializer.NewCodecFactory(scheme.Scheme).UniversalDecoder()
76+
err = apimachineryRuntime.DecodeInto(decoder, []byte(imagePolicyTemplate), clusterPolicy)
77+
if err != nil {
78+
return err
79+
}
80+
81+
if err := driver.Create(context.Background(), clusterPolicy, &runtimeClient.CreateOptions{}); err != nil {
82+
if !apierrors.IsAlreadyExists(err) {
83+
return fmt.Errorf("unable to create image policy: %v", err)
84+
}
85+
86+
if err := driver.Update(context.Background(), clusterPolicy, &runtimeClient.UpdateOptions{}); err != nil {
87+
return fmt.Errorf("unable to update image policy: %v", err)
88+
}
89+
}
90+
return nil
91+
}

Diff for: pkg/imagepolicy/kyverno/util.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package kyverno
2+
3+
import (
4+
"bytes"
5+
"text/template"
6+
)
7+
8+
// SubsituteTemplate fills out the templates based on the context
9+
func SubsituteTemplate(tmpl string, context interface{}) (string, error) {
10+
// Use [[]] as identifier to avoid conflicts
11+
t, tmplPrsErr := template.New("test").Delims("[[", "]]").Option("missingkey=zero").Parse(tmpl)
12+
if tmplPrsErr != nil {
13+
return "", tmplPrsErr
14+
}
15+
writer := bytes.NewBuffer([]byte{})
16+
if err := t.Execute(writer, context); nil != err {
17+
return "", err
18+
}
19+
20+
return writer.String(), nil
21+
}

Diff for: vendor/bitbucket.org/creachadair/shell/LICENSE

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: vendor/bitbucket.org/creachadair/shell/README.md

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: vendor/bitbucket.org/creachadair/shell/bitbucket-pipelines.yml

+23
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)