code.gitea.io/gitea@v1.21.7/services/packages/container/cleanup.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package container
     5  
     6  import (
     7  	"context"
     8  	"time"
     9  
    10  	packages_model "code.gitea.io/gitea/models/packages"
    11  	container_model "code.gitea.io/gitea/models/packages/container"
    12  	container_module "code.gitea.io/gitea/modules/packages/container"
    13  	"code.gitea.io/gitea/modules/util"
    14  	packages_service "code.gitea.io/gitea/services/packages"
    15  
    16  	digest "github.com/opencontainers/go-digest"
    17  )
    18  
    19  // Cleanup removes expired container data
    20  func Cleanup(ctx context.Context, olderThan time.Duration) error {
    21  	if err := cleanupExpiredBlobUploads(ctx, olderThan); err != nil {
    22  		return err
    23  	}
    24  	return cleanupExpiredUploadedBlobs(ctx, olderThan)
    25  }
    26  
    27  // cleanupExpiredBlobUploads removes expired blob uploads
    28  func cleanupExpiredBlobUploads(ctx context.Context, olderThan time.Duration) error {
    29  	pbus, err := packages_model.FindExpiredBlobUploads(ctx, olderThan)
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	for _, pbu := range pbus {
    35  		if err := RemoveBlobUploadByID(ctx, pbu.ID); err != nil {
    36  			return err
    37  		}
    38  	}
    39  
    40  	return nil
    41  }
    42  
    43  // cleanupExpiredUploadedBlobs removes expired uploaded blobs not referenced by a manifest
    44  func cleanupExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) error {
    45  	pfs, err := container_model.SearchExpiredUploadedBlobs(ctx, olderThan)
    46  	if err != nil {
    47  		return err
    48  	}
    49  
    50  	for _, pf := range pfs {
    51  		if err := packages_service.DeletePackageFile(ctx, pf); err != nil {
    52  			return err
    53  		}
    54  	}
    55  
    56  	pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
    57  		Type: packages_model.TypeContainer,
    58  		Version: packages_model.SearchValue{
    59  			ExactMatch: true,
    60  			Value:      container_model.UploadVersion,
    61  		},
    62  		IsInternal: util.OptionalBoolTrue,
    63  		HasFiles:   util.OptionalBoolFalse,
    64  	})
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	for _, pv := range pvs {
    70  		if err := packages_model.DeleteAllProperties(ctx, packages_model.PropertyTypeVersion, pv.ID); err != nil {
    71  			return err
    72  		}
    73  
    74  		if err := packages_model.DeleteVersionByID(ctx, pv.ID); err != nil {
    75  			return err
    76  		}
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func ShouldBeSkipped(ctx context.Context, pcr *packages_model.PackageCleanupRule, p *packages_model.Package, pv *packages_model.PackageVersion) (bool, error) {
    83  	// Always skip the "latest" tag
    84  	if pv.LowerVersion == "latest" {
    85  		return true, nil
    86  	}
    87  
    88  	// Check if the version is a digest (or untagged)
    89  	if digest.Digest(pv.LowerVersion).Validate() == nil {
    90  		// Check if there is another manifest referencing this version
    91  		has, err := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{
    92  			PackageID: p.ID,
    93  			Properties: map[string]string{
    94  				container_module.PropertyManifestReference: pv.LowerVersion,
    95  			},
    96  		})
    97  		if err != nil {
    98  			return false, err
    99  		}
   100  
   101  		// Skip it if the version is referenced
   102  		if has {
   103  			return true, nil
   104  		}
   105  	}
   106  
   107  	return false, nil
   108  }