drone/registry/app/store/database.go
Shivanand Sonnad 8b277e62d7 feat: [AH-1223]: Implement delete version for non oci package types (#3684)
* feat: [AH-1223]: fix failing go lint
* feat: [AH-1223]: fix failing go lint
* feat: [AH-1223]: file name change
* feat: [AH-1223]: file name change
* feat: [AH-1223]: fix go lint errors
* feat: [AH-1223]: add RPM package type in switch case
* feat: [AH-1223]: cascade delete download_stats and bandwidth_stats
* feat: [AH-1223]: resolve PR comments
* feat: [AH-1223]: resolve PR comments
* feat: [AH-1223]: fix failing go lint checks
* feat: [AH-1223]: add different switch case for delete based on package type
* feat: [AH-1223]: Implement delete version for non oci package types
2025-04-18 09:01:07 +00:00

669 lines
21 KiB
Go

// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package store
import (
"context"
"time"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/types"
gitnesstypes "github.com/harness/gitness/types"
"github.com/lib/pq"
"github.com/opencontainers/go-digest"
)
type MediaTypesRepository interface {
MapMediaType(ctx context.Context, mediaType string) (int64, error)
MediaTypeExists(ctx context.Context, mediaType string) (bool, error)
}
type BlobRepository interface {
FindByID(ctx context.Context, id int64) (*types.Blob, error)
FindByDigestAndRootParentID(
ctx context.Context, d digest.Digest,
rootParentID int64,
) (*types.Blob, error)
FindByDigestAndRepoID(
ctx context.Context, d digest.Digest, repoID int64,
imageName string,
) (*types.Blob, error)
CreateOrFind(ctx context.Context, b *types.Blob) (*types.Blob, bool, error)
DeleteByID(ctx context.Context, id int64) error
ExistsBlob(
ctx context.Context, repoID int64, d digest.Digest,
image string,
) (bool, error)
TotalSizeByRootParentID(ctx context.Context, id int64) (int64, error)
}
type CleanupPolicyRepository interface {
// GetIdsByRegistryId the CleanupPolicy Ids specified by Registry Key
GetIDsByRegistryID(ctx context.Context, id int64) (ids []int64, err error)
// GetByRegistryId the CleanupPolicy specified by Registry Key
GetByRegistryID(
ctx context.Context,
id int64,
) (cleanupPolicies *[]types.CleanupPolicy, err error)
// Create a CleanupPolicy
Create(
ctx context.Context,
cleanupPolicy *types.CleanupPolicy,
) (id int64, err error)
// Delete the CleanupPolicy specified by repokey and name
Delete(ctx context.Context, id int64) (err error)
// Update the CleanupPolicy.
ModifyCleanupPolicies(
ctx context.Context,
cleanupPolicies *[]types.CleanupPolicy, ids []int64,
) error
}
type ManifestRepository interface {
// FindAll finds all manifests.
FindAll(ctx context.Context) (types.Manifests, error)
// Count counts all manifests.
Count(ctx context.Context) (int, error)
// LayerBlobs finds layer blobs associated with a manifest,
// through the `layers` relationship entity.
LayerBlobs(ctx context.Context, m *types.Manifest) (types.Blobs, error)
// References finds all manifests directly
// referenced by a manifest (if any).
References(ctx context.Context, m *types.Manifest) (types.Manifests, error)
// Create saves a new Manifest. ID value is updated in given request object
Create(ctx context.Context, m *types.Manifest) error
// CreateOrFind attempts to create a manifest. If the manifest already exists
// (same digest in the scope of a given repository)
// that record is loaded from the database into m.
// This is similar to a repositoryStore.FindManifestByDigest followed by
// a Create, but without being prone to race conditions on write
// operations between the corresponding read (FindManifestByDigest2)
// and write (Create) operations.
// Separate Find* and Create method calls should be preferred
// to this when race conditions are not a concern.
CreateOrFind(ctx context.Context, m *types.Manifest) error
AssociateLayerBlob(ctx context.Context, m *types.Manifest, b *types.Blob) error
DissociateLayerBlob(ctx context.Context, m *types.Manifest, b *types.Blob) error
Delete(ctx context.Context, registryID, id int64) error
FindManifestByDigest(
ctx context.Context, repoID int64, imageName string,
digest types.Digest,
) (*types.Manifest, error)
FindManifestByTagName(
ctx context.Context, repoID int64, imageName string,
tag string,
) (*types.Manifest, error)
FindManifestPayloadByTagName(
ctx context.Context,
parentID int64,
repoKey string,
imageName string,
version string,
) (*types.Payload, error)
GetManifestPayload(
ctx context.Context,
parentID int64,
repoKey string,
imageName string,
digest types.Digest,
) (*types.Payload, error)
Get(ctx context.Context, manifestID int64) (*types.Manifest, error)
DeleteManifest(
ctx context.Context, repoID int64,
imageName string, d digest.Digest,
) (bool, error)
ListManifestsBySubject(
ctx context.Context, repoID int64,
id int64,
) (types.Manifests, error)
ListManifestsBySubjectDigest(
ctx context.Context, repoID int64,
digest types.Digest,
) (types.Manifests, error)
}
type ManifestReferenceRepository interface {
AssociateManifest(
ctx context.Context, ml *types.Manifest,
m *types.Manifest,
) error
DissociateManifest(
ctx context.Context, ml *types.Manifest,
m *types.Manifest,
) error
}
type OCIImageIndexMappingRepository interface {
Create(ctx context.Context, ociManifest *types.OCIImageIndexMapping) error
GetAllByChildDigest(ctx context.Context, registryID int64, imageName string, childDigest types.Digest) (
[]*types.OCIImageIndexMapping, error,
)
}
type LayerRepository interface {
AssociateLayerBlob(ctx context.Context, m *types.Manifest, b *types.Blob) error
}
type TagRepository interface {
// CreateOrUpdate upsert a tag. A tag with a given name
// on a given repository may not exist (in which case it should be
// inserted), already exist and point to the same manifest
// (in which case nothing needs to be done) or already exist but
// points to a different manifest (in which case it should be updated).
CreateOrUpdate(ctx context.Context, t *types.Tag) error
LockTagByNameForUpdate(
ctx context.Context, repoID int64,
name string,
) (bool, error)
DeleteTagByName(
ctx context.Context, repoID int64,
name string,
) (bool, error)
DeleteTagByManifestID(
ctx context.Context, repoID int64,
manifestID int64,
) (bool, error)
TagsPaginated(
ctx context.Context, repoID int64, image string,
filters types.FilterParams,
) ([]*types.Tag, error)
HasTagsAfterName(
ctx context.Context, repoID int64,
filters types.FilterParams,
) (bool, error)
GetAllArtifactsByParentID(
ctx context.Context, parentID int64,
registryIDs *[]string, sortByField string,
sortByOrder string, limit int, offset int, search string,
latestVersion bool, packageTypes []string,
) (*[]types.ArtifactMetadata, error)
CountAllArtifactsByParentID(
ctx context.Context, parentID int64,
registryIDs *[]string, search string,
latestVersion bool, packageTypes []string,
) (int64, error)
GetAllArtifactsByRepo(
ctx context.Context, parentID int64, repoKey string,
sortByField string, sortByOrder string,
limit int, offset int, search string, labels []string,
) (*[]types.ArtifactMetadata, error)
GetLatestTagMetadata(
ctx context.Context,
parentID int64,
repoKey string,
imageName string,
) (*types.ArtifactMetadata, error)
GetLatestTagName(
ctx context.Context, parentID int64, repoKey string,
imageName string,
) (string, error)
GetTagMetadata(
ctx context.Context,
parentID int64,
repoKey string,
imageName string,
name string,
) (*types.TagMetadata, error)
CountAllArtifactsByRepo(
ctx context.Context, parentID int64, repoKey string,
search string, labels []string,
) (int64, error)
GetTagDetail(
ctx context.Context, repoID int64, imageName string,
name string,
) (*types.TagDetail, error)
GetLatestTag(ctx context.Context, repoID int64, imageName string) (*types.Tag, error)
GetAllTagsByRepoAndImage(
ctx context.Context,
parentID int64,
repoKey string,
image string,
sortByField string,
sortByOrder string,
limit int,
offset int,
search string,
) (*[]types.TagMetadata, error)
DeleteTag(ctx context.Context, registryID int64, imageName string, name string) (err error)
CountAllTagsByRepoAndImage(
ctx context.Context, parentID int64, repoKey string,
image string, search string,
) (int64, error)
FindTag(
ctx context.Context, repoID int64, imageName string,
name string,
) (*types.Tag, error)
DeleteTagsByImageName(
ctx context.Context, registryID int64,
imageName string,
) (err error)
}
// UpstreamProxyConfig holds the record of a config of upstream proxy in DB.
type UpstreamProxyConfig struct {
ID int64
RegistryID int64
Source string
URL string
AuthType string
UserName string
Password string
Token string
CreatedAt time.Time
UpdatedAt time.Time
}
type UpstreamProxyConfigRepository interface {
// Get the upstreamproxy specified by ID
Get(ctx context.Context, id int64) (upstreamProxy *types.UpstreamProxy, err error)
// GetByRepoKey gets the upstreamproxy specified by registry key
GetByRegistryIdentifier(
ctx context.Context,
parentID int64,
repoKey string,
) (upstreamProxy *types.UpstreamProxy, err error)
// GetByParentUniqueId gets the upstreamproxy specified by parent id and parent unique id
GetByParentID(ctx context.Context, parentID string) (
upstreamProxies *[]types.UpstreamProxy,
err error,
)
// Create a upstreamProxyConfig
Create(ctx context.Context, upstreamproxyRecord *types.UpstreamProxyConfig) (
id int64,
err error,
)
// Delete the upstreamProxyConfig specified by registry key
Delete(ctx context.Context, parentID int64, repoKey string) (err error)
// Update updates the upstreamproxy.
Update(ctx context.Context, upstreamproxyRecord *types.UpstreamProxyConfig) (err error)
GetAll(
ctx context.Context,
parentID int64,
packageTypes []string,
sortByField string,
sortByOrder string,
limit int,
offset int,
search string,
) (upstreamProxies *[]types.UpstreamProxy, err error)
CountAll(
ctx context.Context, parentID string, packageTypes []string,
search string,
) (count int64, err error)
}
type RegistryMetadata struct {
RegID string
RegIdentifier string
Description string
PackageType artifact.PackageType
Type artifact.RegistryType
LastModified time.Time
URL string
Labels pq.StringArray
ArtifactCount int64
DownloadCount int64
Size int64
}
type RegistryRepository interface {
// Get the repository specified by ID
Get(ctx context.Context, id int64) (repository *types.Registry, err error)
// GetByName gets the repository specified by name
GetByIDIn(
ctx context.Context, ids []int64,
) (registries *[]types.Registry, err error)
// GetByName gets the repository specified by parent id and name
GetByParentIDAndName(
ctx context.Context, parentID int64,
name string,
) (registry *types.Registry, err error)
GetByRootParentIDAndName(
ctx context.Context, parentID int64,
name string,
) (registry *types.Registry, err error)
// Create a repository
Create(ctx context.Context, repository *types.Registry) (id int64, err error)
// Delete the repository specified by ID
Delete(ctx context.Context, parentID int64, name string) (err error)
// Update updates the repository. Only the properties specified by "props" will be updated if it is set
Update(ctx context.Context, repository *types.Registry) (err error)
GetAll(
ctx context.Context,
parentID int64,
packageTypes []string,
sortByField string,
sortByOrder string,
limit int,
offset int,
search string,
repoType string,
recursive bool,
) (repos *[]RegistryMetadata, err error)
CountAll(
ctx context.Context, parentID int64, packageTypes []string,
search string, repoType string,
) (count int64, err error)
FetchUpstreamProxyIDs(
ctx context.Context, repokeys []string,
parentID int64,
) (ids []int64, err error)
FetchRegistriesIDByUpstreamProxyID(
ctx context.Context, upstreamProxyID string,
rootParentID int64,
) (ids []int64, err error)
FetchUpstreamProxyKeys(ctx context.Context, ids []int64) (repokeys []string, err error)
Count(ctx context.Context) (int64, error)
}
type RegistryBlobRepository interface {
LinkBlob(
ctx context.Context, imageName string,
registry *types.Registry, blobID int64,
) error
UnlinkBlob(
ctx context.Context, imageName string,
registry *types.Registry, blobID int64,
) (bool, error)
}
type ImageRepository interface {
// Get an Artifact specified by ID
Get(ctx context.Context, id int64) (*types.Image, error)
// Get an Artifact specified by Artifact Name
GetByName(
ctx context.Context, registryID int64,
name string,
) (*types.Image, error)
// Get the Labels specified by Parent ID and Repo
GetLabelsByParentIDAndRepo(
ctx context.Context, parentID int64,
repo string, limit int, offset int,
search string,
) (labels []string, err error)
// Count the Labels specified by Parent ID and Repo
CountLabelsByParentIDAndRepo(
ctx context.Context, parentID int64,
repo, search string,
) (count int64, err error)
// Get an Artifact specified by Artifact Name
GetByRepoAndName(
ctx context.Context, parentID int64,
repo string, name string,
) (*types.Image, error)
// Create an Image
CreateOrUpdate(ctx context.Context, image *types.Image) error
// Update an Image
Update(ctx context.Context, artifact *types.Image) (err error)
UpdateStatus(ctx context.Context, artifact *types.Image) (err error)
DeleteByRegistryID(ctx context.Context, registryID int64) (err error)
DeleteBandwidthStatByRegistryID(ctx context.Context, registryID int64) (err error)
DeleteDownloadStatByRegistryID(ctx context.Context, registryID int64) (err error)
DeleteByImageNameAndRegID(ctx context.Context, regID int64, image string) (err error)
DeleteByImageNameIfNoLinkedArtifacts(ctx context.Context, regID int64, image string) (err error)
}
type ArtifactRepository interface {
// Get an Artifact specified by ID
GetByName(ctx context.Context, imageID int64, version string) (*types.Artifact, error)
// Create an Artifact
CreateOrUpdate(ctx context.Context, artifact *types.Artifact) error
Count(ctx context.Context) (int64, error)
GetAllArtifactsByParentID(
ctx context.Context, id int64,
i *[]string, field string, order string,
limit int, offset int, term string,
version bool, packageTypes []string,
) (*[]types.ArtifactMetadata, error)
CountAllArtifactsByParentID(
ctx context.Context, parentID int64,
registryIDs *[]string, search string, latestVersion bool, packageTypes []string,
) (int64, error)
GetArtifactsByRepo(
ctx context.Context, parentID int64, repoKey string,
sortByField string, sortByOrder string, limit int, offset int, search string,
labels []string,
) (*[]types.ArtifactMetadata, error)
CountArtifactsByRepo(
ctx context.Context, parentID int64, repoKey string,
search string, labels []string,
) (int64, error)
GetLatestArtifactMetadata(
ctx context.Context, id int64, identifier string,
image string,
) (*types.ArtifactMetadata, error)
GetAllVersionsByRepoAndImage(
ctx context.Context, id int64, identifier string, image string,
field string, order string, limit int, offset int, term string,
) (*[]types.NonOCIArtifactMetadata, error)
CountAllVersionsByRepoAndImage(
ctx context.Context, parentID int64,
repoKey string, image string, search string,
) (int64, error)
GetArtifactMetadata(
ctx context.Context, id int64, identifier string,
image string, version string,
) (*types.ArtifactMetadata, error)
GetByRegistryIDAndImage(ctx context.Context, registryID int64, image string) (
*[]types.Artifact,
error,
)
DeleteByImageNameAndRegistryID(ctx context.Context, regID int64, image string) (err error)
DeleteByVersionAndImageName(ctx context.Context, image string, version string, regID int64) (err error)
GetLatestByImageID(ctx context.Context, imageID int64) (*types.Artifact, error)
GetAllArtifactsByRepo(
ctx context.Context, registryID int64, batchSize int, artifactID int64,
) (*[]types.ArtifactMetadata, error)
}
type DownloadStatRepository interface {
Create(ctx context.Context, downloadStat *types.DownloadStat) error
GetTotalDownloadsForImage(ctx context.Context, imageID int64) (int64, error)
GetTotalDownloadsForManifests(
ctx context.Context,
artifactVersion []string,
imageID int64,
) (map[string]int64, error)
CreateByRegistryIDImageAndArtifactName(ctx context.Context, regID int64, image string, artifactName string) error
GetTotalDownloadsForArtifactID(ctx context.Context, artifactID int64) (int64, error)
}
type BandwidthStatRepository interface {
Create(ctx context.Context, bandwidthStat *types.BandwidthStat) error
}
type GCBlobTaskRepository interface {
FindAll(ctx context.Context) ([]*types.GCBlobTask, error)
FindAndLockBefore(
ctx context.Context, blobID int64,
date time.Time,
) (*types.GCBlobTask, error)
Count(ctx context.Context) (int, error)
Next(ctx context.Context) (*types.GCBlobTask, error)
Reschedule(ctx context.Context, b *types.GCBlobTask, d time.Duration) error
Postpone(ctx context.Context, b *types.GCBlobTask, d time.Duration) error
IsDangling(ctx context.Context, b *types.GCBlobTask) (bool, error)
Delete(ctx context.Context, b *types.GCBlobTask) error
}
type GCManifestTaskRepository interface {
FindAndLock(
ctx context.Context, registryID,
manifestID int64,
) (*types.GCManifestTask, error)
FindAndLockBefore(
ctx context.Context, registryID, manifestID int64,
date time.Time,
) (*types.GCManifestTask, error)
FindAndLockNBefore(
ctx context.Context, registryID int64,
manifestIDs []int64, date time.Time,
) ([]*types.GCManifestTask, error)
Next(ctx context.Context) (*types.GCManifestTask, error)
Postpone(ctx context.Context, b *types.GCManifestTask, d time.Duration) error
IsDangling(ctx context.Context, b *types.GCManifestTask) (bool, error)
Delete(ctx context.Context, b *types.GCManifestTask) error
DeleteManifest(ctx context.Context, registryID, id int64) (*digest.Digest, error)
}
type NodesRepository interface {
// Get a node specified by ID
Get(ctx context.Context, id int64) (*types.Node, error)
// Get a node specified by node Name and registry id
GetByNameAndRegistryID(
ctx context.Context, registryID int64,
name string,
) (*types.Node, error)
FindByPathAndRegistryID(
ctx context.Context, registryID int64, path string,
) (*types.Node, error)
CountByPathAndRegistryID(
ctx context.Context, registryID int64, path string,
) (int64, error)
// Create a node
Create(ctx context.Context, node *types.Node) error
// delete a node
DeleteByID(ctx context.Context, id int64) (err error)
DeleteByRegistryID(ctx context.Context, id int64) (err error)
GetByPathAndRegistryID(
ctx context.Context, registryID int64,
path string,
) (*types.Node, error)
GetFilesMetadataByPathAndRegistryID(
ctx context.Context, registryID int64, path string,
sortByField string,
sortByOrder string,
limit int,
offset int,
search string,
) (*[]types.FileNodeMetadata, error)
DeleteByNodePathAndRegistryID(ctx context.Context, nodePath string, regID int64) (err error)
}
type GenericBlobRepository interface {
FindByID(ctx context.Context, id string) (*types.GenericBlob, error)
FindBySha256AndRootParentID(
ctx context.Context, sha256 string,
rootParentID int64,
) (*types.GenericBlob, error)
Create(ctx context.Context, gb *types.GenericBlob) (bool, error)
DeleteByID(ctx context.Context, id string) error
TotalSizeByRootParentID(ctx context.Context, id int64) (int64, error)
}
type WebhooksRepository interface {
Create(ctx context.Context, webhook *gitnesstypes.WebhookCore) error
GetByRegistryAndIdentifier(
ctx context.Context,
registryID int64,
webhookIdentifier string,
) (*gitnesstypes.WebhookCore, error)
Find(ctx context.Context, webhookID int64) (*gitnesstypes.WebhookCore, error)
ListByRegistry(
ctx context.Context,
sortByField string,
sortByOrder string,
limit int,
offset int,
search string,
registryID int64,
) ([]*gitnesstypes.WebhookCore, error)
ListAllByRegistry(
ctx context.Context,
parents []gitnesstypes.WebhookParentInfo,
) ([]*gitnesstypes.WebhookCore, error)
CountAllByRegistry(
ctx context.Context,
registryID int64,
search string,
) (int64, error)
Update(ctx context.Context, webhook *gitnesstypes.WebhookCore) error
DeleteByRegistryAndIdentifier(ctx context.Context, registryID int64, webhookIdentifier string) error
UpdateOptLock(
ctx context.Context, hook *gitnesstypes.WebhookCore,
mutateFn func(hook *gitnesstypes.WebhookCore) error,
) (*gitnesstypes.WebhookCore, error)
}
type WebhooksExecutionRepository interface {
Find(ctx context.Context, id int64) (*gitnesstypes.WebhookExecutionCore, error)
// Create creates a new webhook execution entry.
Create(ctx context.Context, hook *gitnesstypes.WebhookExecutionCore) error
// ListForWebhook lists the webhook executions for a given webhook id.
ListForWebhook(
ctx context.Context,
webhookID int64,
limit int,
page int,
size int,
) ([]*gitnesstypes.WebhookExecutionCore, error)
CountForWebhook(ctx context.Context, webhookID int64) (int64, error)
// ListForTrigger lists the webhook executions for a given trigger id.
ListForTrigger(ctx context.Context, triggerID string) ([]*gitnesstypes.WebhookExecutionCore, error)
}
type PackageTagRepository interface {
FindByImageNameAndRegID(ctx context.Context, image string, regID int64) ([]*types.PackageTagMetadata, error)
Create(ctx context.Context, tag *types.PackageTag) (string, error)
DeleteByTagAndImageName(ctx context.Context, tag string, image string, regID int64) error
DeleteByImageNameAndRegID(ctx context.Context, image string, regID int64) error
}