mirror of
https://github.com/project-zot/zot.git
synced 2026-06-16 04:17:55 +08:00
image level lint: enforce manifest mandatory annotations
closes #536 Signed-off-by: Lisca Ana-Roberta <ana.kagome@yahoo.com>
This commit is contained in:
committed by
Andrei Aaron
parent
3d72dad507
commit
87fc941b3c
@@ -274,7 +274,8 @@ func syncOneImage(imageChannel chan error, cfg Config, storeController storage.S
|
||||
imageChannel <- nil
|
||||
}
|
||||
|
||||
func syncRun(regCfg RegistryConfig, localRepo, remoteRepo, tag string, utils syncContextUtils,
|
||||
func syncRun(regCfg RegistryConfig,
|
||||
localRepo, remoteRepo, tag string, utils syncContextUtils,
|
||||
log log.Logger,
|
||||
) (bool, error) {
|
||||
upstreamImageRef, err := getImageRef(utils.upstreamAddr, remoteRepo, tag)
|
||||
|
||||
@@ -196,7 +196,8 @@ func syncCosignSignature(client *resty.Client, imageStore storage.ImageStore,
|
||||
}
|
||||
|
||||
// push manifest
|
||||
_, err = imageStore.PutImageManifest(localRepo, cosignTag, ispec.MediaTypeImageManifest, cosignManifestBuf)
|
||||
_, err = imageStore.PutImageManifest(localRepo, cosignTag,
|
||||
ispec.MediaTypeImageManifest, cosignManifestBuf)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Msg("couldn't upload cosign manifest")
|
||||
|
||||
@@ -296,7 +296,8 @@ func getUpstreamContext(regCfg *RegistryConfig, credentials Credentials) *types.
|
||||
}
|
||||
|
||||
// nolint:gocyclo // offloading some of the functionalities from here would make the code harder to follow
|
||||
func syncRegistry(ctx context.Context, regCfg RegistryConfig, upstreamURL string,
|
||||
func syncRegistry(ctx context.Context, regCfg RegistryConfig,
|
||||
upstreamURL string,
|
||||
storeController storage.StoreController, localCtx *types.SystemContext,
|
||||
policyCtx *signature.PolicyContext, credentials Credentials,
|
||||
retryOptions *retry.RetryOptions, log log.Logger,
|
||||
@@ -509,7 +510,6 @@ func syncRegistry(ctx context.Context, regCfg RegistryConfig, upstreamURL string
|
||||
}
|
||||
// push from cache to repo
|
||||
err = pushSyncedLocalImage(localRepo, tag, localCachePath, imageStore, log)
|
||||
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Msgf("error while pushing synced cached image %s",
|
||||
@@ -573,7 +573,8 @@ func getLocalContexts(log log.Logger) (*types.SystemContext, *signature.PolicyCo
|
||||
return localCtx, policyContext, nil
|
||||
}
|
||||
|
||||
func Run(ctx context.Context, cfg Config, storeController storage.StoreController,
|
||||
func Run(ctx context.Context, cfg Config,
|
||||
storeController storage.StoreController,
|
||||
wtgrp *goSync.WaitGroup, logger log.Logger,
|
||||
) error {
|
||||
var credentialsFile CredentialsFile
|
||||
|
||||
@@ -61,7 +61,9 @@ func TestInjectSyncUtils(t *testing.T) {
|
||||
|
||||
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||
metrics := monitoring.NewMetricsServer(false, log)
|
||||
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay, false, false, log, metrics)
|
||||
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay,
|
||||
false, false, log, metrics, nil,
|
||||
)
|
||||
injected = test.InjectFailure(0)
|
||||
|
||||
_, err = getLocalCachePath(imageStore, testImage)
|
||||
@@ -147,7 +149,8 @@ func TestSyncInternal(t *testing.T) {
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
So(Run(ctx, cfg, storage.StoreController{}, new(goSync.WaitGroup), log.NewLogger("debug", "")), ShouldNotBeNil)
|
||||
So(Run(ctx, cfg, storage.StoreController{},
|
||||
new(goSync.WaitGroup), log.NewLogger("debug", "")), ShouldNotBeNil)
|
||||
|
||||
_, err = getFileCredentials("/invalid/path/to/file")
|
||||
So(err, ShouldNotBeNil)
|
||||
@@ -157,7 +160,8 @@ func TestSyncInternal(t *testing.T) {
|
||||
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||
metrics := monitoring.NewMetricsServer(false, log)
|
||||
|
||||
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay, false, false, log, metrics)
|
||||
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay,
|
||||
false, false, log, metrics, nil)
|
||||
|
||||
err := os.Chmod(imageStore.RootDir(), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -340,7 +344,8 @@ func TestSyncInternal(t *testing.T) {
|
||||
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||
metrics := monitoring.NewMetricsServer(false, log)
|
||||
|
||||
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay, false, false, log, metrics)
|
||||
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay,
|
||||
false, false, log, metrics, nil)
|
||||
|
||||
refs := ReferenceList{[]artifactspec.Descriptor{
|
||||
{
|
||||
@@ -422,7 +427,8 @@ func TestSyncInternal(t *testing.T) {
|
||||
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||
metrics := monitoring.NewMetricsServer(false, log)
|
||||
|
||||
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay, false, false, log, metrics)
|
||||
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay,
|
||||
false, false, log, metrics, nil)
|
||||
|
||||
storeController := storage.StoreController{}
|
||||
storeController.DefaultStore = imageStore
|
||||
@@ -443,7 +449,8 @@ func TestSyncInternal(t *testing.T) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
testImageStore := storage.NewImageStore(testRootDir, false, storage.DefaultGCDelay, false, false, log, metrics)
|
||||
testImageStore := storage.NewImageStore(testRootDir, false,
|
||||
storage.DefaultGCDelay, false, false, log, metrics, nil)
|
||||
manifestContent, _, _, err := testImageStore.GetImageManifest(testImage, testImageTag)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
||||
@@ -862,6 +862,107 @@ func TestConfigReloader(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestMandatoryAnnotations(t *testing.T) {
|
||||
Convey("Verify mandatory annotations failing - on demand disabled", t, func() {
|
||||
updateDuration, _ := time.ParseDuration("30m")
|
||||
|
||||
sctlr, srcBaseURL, _, _, _ := startUpstreamServer(t, false, false)
|
||||
|
||||
defer func() {
|
||||
sctlr.Shutdown()
|
||||
}()
|
||||
|
||||
regex := ".*"
|
||||
var semver bool
|
||||
tlsVerify := false
|
||||
|
||||
syncRegistryConfig := sync.RegistryConfig{
|
||||
Content: []sync.Content{
|
||||
{
|
||||
Prefix: testImage,
|
||||
Tags: &sync.Tags{
|
||||
Regex: ®ex,
|
||||
Semver: &semver,
|
||||
},
|
||||
},
|
||||
},
|
||||
URLs: []string{srcBaseURL},
|
||||
OnDemand: false,
|
||||
PollInterval: updateDuration,
|
||||
TLSVerify: &tlsVerify,
|
||||
}
|
||||
|
||||
defaultVal := true
|
||||
syncConfig := &sync.Config{
|
||||
Enable: &defaultVal,
|
||||
Registries: []sync.RegistryConfig{syncRegistryConfig},
|
||||
}
|
||||
|
||||
destPort := test.GetFreePort()
|
||||
destConfig := config.New()
|
||||
destClient := resty.New()
|
||||
|
||||
destBaseURL := test.GetBaseURL(destPort)
|
||||
|
||||
destConfig.HTTP.Port = destPort
|
||||
|
||||
destDir := t.TempDir()
|
||||
|
||||
destConfig.Storage.RootDirectory = destDir
|
||||
destConfig.Storage.Dedupe = false
|
||||
destConfig.Storage.GC = false
|
||||
|
||||
destConfig.Extensions = &extconf.ExtensionConfig{}
|
||||
destConfig.Extensions.Sync = syncConfig
|
||||
|
||||
logFile, err := ioutil.TempFile("", "zot-log*.txt")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
destConfig.Log.Output = logFile.Name()
|
||||
|
||||
lintEnabled := true
|
||||
destConfig.Extensions.Lint = &extconf.LintConfig{}
|
||||
destConfig.Extensions.Lint.Enabled = &lintEnabled
|
||||
destConfig.Extensions.Lint.MandatoryAnnotations = []string{"annot1", "annot2", "annot3"}
|
||||
|
||||
dctlr := api.NewController(destConfig)
|
||||
|
||||
go func() {
|
||||
// this blocks
|
||||
if err := dctlr.Run(context.Background()); err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// wait till ready
|
||||
for {
|
||||
_, err := destClient.R().Get(destBaseURL)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
dctlr.Shutdown()
|
||||
}()
|
||||
|
||||
// give it time to set up sync
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifest/0.0.1")
|
||||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 404)
|
||||
|
||||
data, err := os.ReadFile(logFile.Name())
|
||||
t.Logf("downstream log: %s", string(data))
|
||||
So(err, ShouldBeNil)
|
||||
So(string(data), ShouldContainSubstring, "couldn't upload manifest because of missing annotations")
|
||||
})
|
||||
}
|
||||
|
||||
func TestBadTLS(t *testing.T) {
|
||||
Convey("Verify sync TLS feature", t, func() {
|
||||
updateDuration, _ := time.ParseDuration("30m")
|
||||
|
||||
@@ -270,7 +270,9 @@ func pushSyncedLocalImage(localRepo, tag, localCachePath string,
|
||||
log.Info().Msgf("pushing synced local image %s/%s:%s to local registry", localCachePath, localRepo, tag)
|
||||
|
||||
metrics := monitoring.NewMetricsServer(false, log)
|
||||
cacheImageStore := storage.NewImageStore(localCachePath, false, storage.DefaultGCDelay, false, false, log, metrics)
|
||||
|
||||
cacheImageStore := storage.NewImageStore(localCachePath, false,
|
||||
storage.DefaultGCDelay, false, false, log, metrics, nil)
|
||||
|
||||
manifestContent, _, _, err := cacheImageStore.GetImageManifest(localRepo, tag)
|
||||
if err != nil {
|
||||
@@ -331,8 +333,16 @@ func pushSyncedLocalImage(localRepo, tag, localCachePath string,
|
||||
}
|
||||
}
|
||||
|
||||
_, err = imageStore.PutImageManifest(localRepo, tag, ispec.MediaTypeImageManifest, manifestContent)
|
||||
_, err = imageStore.PutImageManifest(localRepo, tag,
|
||||
ispec.MediaTypeImageManifest, manifestContent)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrImageLintAnnotations) {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Msg("couldn't upload manifest because of missing annotations")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Msg("couldn't upload manifest")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user