registry/datastore/models/models.go (213 lines of code) (raw):
package models
import (
"database/sql"
"database/sql/driver"
"encoding/json"
"strings"
"time"
"github.com/opencontainers/go-digest"
)
// Payload implements sql/driver.Valuer interface, allowing pgx to use
// the PostgreSQL simple protocol.
type Payload json.RawMessage
// Value returns the payload serialized as a []byte.
func (p Payload) Value() (driver.Value, error) {
return json.RawMessage(p).MarshalJSON()
}
// Namespace represents a root repository.
type Namespace struct {
ID int64
Name string
CreatedAt time.Time
UpdatedAt sql.NullTime
}
type Repository struct {
ID int64
NamespaceID int64
Name string
Path string
ParentID sql.NullInt64
CreatedAt time.Time
UpdatedAt sql.NullTime
// This is a temporary attribute for the duration of https://gitlab.com/gitlab-org/container-registry/-/issues/570,
// and is only here to allow us to test selects and inserts for soft-deleted repositories:
DeletedAt sql.NullTime
// The Size of the repository in bytes. The Size of a repository can be 0, so we use a pointer
// to differentiate between a "0 byte" size repository and a repository that has nil size attribute
// (i.e the attribute was not cached or was invalidated).
// This value is not saved in the DB so we don't need to use a sql.NullInt64 type.
Size *int64
// LastPublishedAt is set to the timestamp of the latest published tag in the repository. This should equal to
// MAX(GREATEST(created_at, updated_at)) among all tags.
LastPublishedAt sql.NullTime
}
// IsTopLevel identifies whether a repository is a top-level repository or not.
func (r *Repository) IsTopLevel() bool {
return !strings.Contains(r.Path, "/")
}
// TopLevelPathSegment returns the top-level path segment.
func (r *Repository) TopLevelPathSegment() string {
return strings.Split(r.Path, "/")[0]
}
// Repositories is a slice of Repository pointers.
type Repositories []*Repository
type Configuration struct {
MediaType string
Digest digest.Digest
// Payload is the JSON payload of a manifest configuration. For operational safety reasons,
// a payload is only saved in this attribute if its size does not exceed a predefined
// limit (see handlers.dbConfigSizeLimit).
Payload Payload
}
type Manifest struct {
ID int64
NamespaceID int64
RepositoryID int64
TotalSize int64
SchemaVersion int
MediaType string
ArtifactType sql.NullString
Digest digest.Digest
Payload Payload
Configuration *Configuration
SubjectID sql.NullInt64
NonConformant bool
// NonDistributableLayers identifies whether a manifest references foreign/non-distributable layers. For now, we are
// not registering metadata about these layers, but we may wish to backfill that metadata in the future by parsing
// the manifest payload.
NonDistributableLayers bool
CreatedAt time.Time
}
// Manifests is a slice of Manifest pointers.
type Manifests []*Manifest
type Tag struct {
ID int64
NamespaceID int64
Name string
RepositoryID int64
ManifestID int64
CreatedAt time.Time
UpdatedAt sql.NullTime
}
// Tags is a slice of Tag pointers.
type Tags []*Tag
// NullDigest is used to represent a digest.Digest that might be empty. Note that the value of Valid does not
// necessarily guarantee that the value of Digest is/is not a valid digest, only that it is/is not an empty string. So
// this is similar to sql.NullString, but embeds a digest.Digest instead of a plain string for convenience. It is the
// responsibility of the code that initializes this struct to guarantee that the value of Digest is a valid digest.
type NullDigest struct {
Digest digest.Digest
Valid bool
}
// TagDetail is a virtual entity with no parallel on the database schema. This provides a set of attributes obtained
// by merging a Tag entity with the corresponding Manifest entity and the GET /gitlab/v1/<name>/tags/list
// and GET /gitlab/v1/<name>/tags/detail API endpoints are its primary use case.
type TagDetail struct {
ManifestID int64
Name string
Digest digest.Digest
ConfigDigest NullDigest
MediaType string
Size int64
CreatedAt time.Time
UpdatedAt sql.NullTime
PublishedAt time.Time
Referrers []TagReferrerDetail
Configuration *Configuration
}
type TagReferrerDetail struct {
Digest string
ArtifactType string
}
type Blob struct {
MediaType string
Digest digest.Digest
Size int64
CreatedAt time.Time
}
// Blobs is a slice of Blob pointers.
type Blobs []*Blob
// GCBlobTask represents a row in the gc_blob_review_queue table.
type GCBlobTask struct {
ReviewAfter time.Time
ReviewCount int
Digest digest.Digest
CreatedAt time.Time
Event string
}
// GCConfigLink represents a row in the gc_blobs_configurations table.
type GCConfigLink struct {
ID int64
NamespaceID int64
RepositoryID int64
ManifestID int64
Digest digest.Digest
}
// GCLayerLink represents a row in the gc_blobs_layers table.
type GCLayerLink struct {
ID int64
NamespaceID int64
RepositoryID int64
LayerID int64
Digest digest.Digest
}
// GCManifestTask represents a row in the gc_manifest_review_queue table.
type GCManifestTask struct {
NamespaceID int64
RepositoryID int64
ManifestID int64
ReviewAfter time.Time
ReviewCount int
CreatedAt time.Time
Event string
}
// GCReviewAfterDefault represents a row in the gc_review_after_defaults table.
type GCReviewAfterDefault struct {
Event string
Value time.Duration
}
// LeaseType defines the types of available leases on repositories
type LeaseType string
// RenameLease is a repository LeaseType for rename operations
var RenameLease LeaseType = "rename_lease"
// RepositoryLease represents a lease (on a new repository space) granted to an existing repository
type RepositoryLease struct {
GrantedTo string
Path string
Type LeaseType
}
// BackgroundMigration is the representation of a BBM.
type BackgroundMigration struct {
ID int
Name string
Status BackgroundMigrationStatus
StartID int
EndID int
BatchSize int
JobName string
TargetTable string
TargetColumn string
ErrorCode BBMErrorCode
}
// BackgroundMigrations is a slice of BackgroundMigration pointers.
type BackgroundMigrations []*BackgroundMigration
// BackgroundMigrationJob is the representation of a BackgroundMigration Job.
type BackgroundMigrationJob struct {
ID int
BBMID int
StartID int
EndID int
Status BackgroundMigrationStatus
Attempts int
JobName string
PaginationColumn string
PaginationTable string
BatchSize int
ErrorCode BBMErrorCode
}
// BackgroundMigrationStatus are the Background Migration and Background Migration job statuses as defined in:
// https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/gitlab/database-background-migrations.md#batch-background-migration-bbm-creation
type BackgroundMigrationStatus int
const (
BackgroundMigrationPaused BackgroundMigrationStatus = iota
BackgroundMigrationActive
BackgroundMigrationFinished
BackgroundMigrationFailed
BackgroundMigrationRunning
)
func (s BackgroundMigrationStatus) String() string {
switch s {
case BackgroundMigrationPaused:
return "paused"
case BackgroundMigrationActive:
return "active"
case BackgroundMigrationFinished:
return "finished"
case BackgroundMigrationFailed:
return "failed"
case BackgroundMigrationRunning:
return "running"
}
return "unknown"
}
// BBMErrorCode represent the failure codes for Background Migration and Background Migration jobs as defined in:
// https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/gitlab/database-background-migrations.md#asynchronous-execution-when-serving-requests-on-the-registry
type BBMErrorCode struct {
sql.NullInt16
}
var (
NullErrCode = BBMErrorCode{sql.NullInt16{Valid: false}}
UnknownBBMErrorCode = BBMErrorCode{sql.NullInt16{Int16: 0, Valid: true}}
InvalidTableBBMErrCode = BBMErrorCode{sql.NullInt16{Int16: 1, Valid: true}}
InvalidColumnBBMErrCode = BBMErrorCode{sql.NullInt16{Int16: 2, Valid: true}}
InvalidJobSignatureBBMErrCode = BBMErrorCode{sql.NullInt16{Int16: 3, Valid: true}}
JobExceedsMaxAttemptBBMErrCode = BBMErrorCode{sql.NullInt16{Int16: 4, Valid: true}}
)
func (s BBMErrorCode) String() string {
switch s.Int16 {
default:
return "unknown"
case InvalidTableBBMErrCode.Int16:
return "invalid_bbm_table"
case InvalidColumnBBMErrCode.Int16:
return "invalid_bbm_column"
case InvalidJobSignatureBBMErrCode.Int16:
return "invalid_job_signature"
case JobExceedsMaxAttemptBBMErrCode.Int16:
return "max_job_retry"
}
}