2019-12-04 09:55:41 +01:00
// Copyright Project Harbor Authors
//
// 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.
2019-12-13 01:49:45 +01:00
package artifact
2019-12-04 09:55:41 +01:00
import (
"encoding/json"
"time"
2020-02-28 10:19:36 +01:00
"github.com/docker/distribution/manifest/manifestlist"
2020-04-02 08:08:52 +02:00
"github.com/goharbor/harbor/src/lib/log"
2019-12-13 01:49:45 +01:00
"github.com/goharbor/harbor/src/pkg/artifact/dao"
2020-03-19 03:48:19 +01:00
"github.com/goharbor/harbor/src/server/v2.0/models"
2019-12-04 09:55:41 +01:00
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
// Artifact is the abstract object managed by Harbor. It hides the
// underlying concrete detail and provides an unified artifact view
// for all users.
type Artifact struct {
2020-02-15 14:48:24 +01:00
ID int64 ` json:"id" `
Type string ` json:"type" ` // image, chart, etc
MediaType string ` json:"media_type" ` // the media type of artifact. Mostly, it's the value of `manifest.config.mediatype`
ManifestMediaType string ` json:"manifest_media_type" ` // the media type of manifest/index
ProjectID int64 ` json:"project_id" `
RepositoryID int64 ` json:"repository_id" `
2020-02-25 14:40:49 +01:00
RepositoryName string ` json:"repository_name" `
2020-02-15 14:48:24 +01:00
Digest string ` json:"digest" `
Size int64 ` json:"size" `
2020-08-05 10:14:36 +02:00
Icon string ` json:"icon" `
2020-02-15 14:48:24 +01:00
PushTime time . Time ` json:"push_time" `
PullTime time . Time ` json:"pull_time" `
ExtraAttrs map [ string ] interface { } ` json:"extra_attrs" ` // only contains the simple attributes specific for the different artifact type, most of them should come from the config layer
Annotations map [ string ] string ` json:"annotations" `
References [ ] * Reference ` json:"references" ` // child artifacts referenced by the parent artifact if the artifact is an index
2019-12-04 09:55:41 +01:00
}
2020-03-19 03:48:19 +01:00
// IsImageIndex returns true when artifact is image index
func ( a * Artifact ) IsImageIndex ( ) bool {
2020-02-28 10:19:36 +01:00
return a . ManifestMediaType == v1 . MediaTypeImageIndex ||
a . ManifestMediaType == manifestlist . MediaTypeManifestList
}
2019-12-04 09:55:41 +01:00
// From converts the database level artifact to the business level object
func ( a * Artifact ) From ( art * dao . Artifact ) {
a . ID = art . ID
a . Type = art . Type
a . MediaType = art . MediaType
a . ManifestMediaType = art . ManifestMediaType
2019-12-13 01:49:45 +01:00
a . ProjectID = art . ProjectID
a . RepositoryID = art . RepositoryID
2020-02-25 14:40:49 +01:00
a . RepositoryName = art . RepositoryName
2019-12-04 09:55:41 +01:00
a . Digest = art . Digest
a . Size = art . Size
2020-08-05 10:14:36 +02:00
a . Icon = art . Icon
2019-12-04 09:55:41 +01:00
a . PushTime = art . PushTime
2019-12-13 01:49:45 +01:00
a . PullTime = art . PullTime
2019-12-04 09:55:41 +01:00
a . ExtraAttrs = map [ string ] interface { } { }
a . Annotations = map [ string ] string { }
if len ( art . ExtraAttrs ) > 0 {
if err := json . Unmarshal ( [ ] byte ( art . ExtraAttrs ) , & a . ExtraAttrs ) ; err != nil {
log . Errorf ( "failed to unmarshal the extra attrs of artifact %d: %v" , art . ID , err )
}
}
if len ( art . Annotations ) > 0 {
if err := json . Unmarshal ( [ ] byte ( art . Annotations ) , & a . Annotations ) ; err != nil {
log . Errorf ( "failed to unmarshal the annotations of artifact %d: %v" , art . ID , err )
}
}
}
// To converts the artifact to the database level object
func ( a * Artifact ) To ( ) * dao . Artifact {
art := & dao . Artifact {
ID : a . ID ,
Type : a . Type ,
MediaType : a . MediaType ,
ManifestMediaType : a . ManifestMediaType ,
2019-12-13 01:49:45 +01:00
ProjectID : a . ProjectID ,
RepositoryID : a . RepositoryID ,
2020-02-25 14:40:49 +01:00
RepositoryName : a . RepositoryName ,
2019-12-04 09:55:41 +01:00
Digest : a . Digest ,
Size : a . Size ,
2020-08-05 10:14:36 +02:00
Icon : a . Icon ,
2019-12-04 09:55:41 +01:00
PushTime : a . PushTime ,
2019-12-13 01:49:45 +01:00
PullTime : a . PullTime ,
2019-12-04 09:55:41 +01:00
}
if len ( a . ExtraAttrs ) > 0 {
attrs , err := json . Marshal ( a . ExtraAttrs )
if err != nil {
log . Errorf ( "failed to marshal the extra attrs of artifact %d: %v" , a . ID , err )
}
art . ExtraAttrs = string ( attrs )
}
if len ( a . Annotations ) > 0 {
annotations , err := json . Marshal ( a . Annotations )
if err != nil {
log . Errorf ( "failed to marshal the annotations of artifact %d: %v" , a . ID , err )
}
art . Annotations = string ( annotations )
}
return art
}
2019-12-13 01:49:45 +01:00
// Reference records the child artifact referenced by parent artifact
type Reference struct {
2020-02-15 14:48:24 +01:00
ID int64 ` json:"id" `
ParentID int64 ` json:"parent_id" `
ChildID int64 ` json:"child_id" `
2020-03-05 03:54:45 +01:00
ChildDigest string ` json:"child_digest" `
2020-02-02 02:13:51 +01:00
Platform * v1 . Platform
2020-03-05 03:54:45 +01:00
URLs [ ] string ` json:"urls" `
Annotations map [ string ] string ` json:"annotations" `
2019-12-04 09:55:41 +01:00
}
2019-12-13 01:49:45 +01:00
// From converts the data level reference to business level
func ( r * Reference ) From ( ref * dao . ArtifactReference ) {
2020-02-15 14:48:24 +01:00
r . ID = ref . ID
2019-12-13 01:49:45 +01:00
r . ParentID = ref . ParentID
r . ChildID = ref . ChildID
2020-03-05 03:54:45 +01:00
r . ChildDigest = ref . ChildDigest
2019-12-13 01:49:45 +01:00
if len ( ref . Platform ) > 0 {
2020-01-16 01:04:22 +01:00
r . Platform = & v1 . Platform { }
if err := json . Unmarshal ( [ ] byte ( ref . Platform ) , r . Platform ) ; err != nil {
2019-12-13 01:49:45 +01:00
log . Errorf ( "failed to unmarshal the platform of reference: %v" , err )
}
}
2020-03-05 03:54:45 +01:00
if len ( ref . URLs ) > 0 {
r . URLs = [ ] string { }
if err := json . Unmarshal ( [ ] byte ( ref . URLs ) , & r . URLs ) ; err != nil {
log . Errorf ( "failed to unmarshal the URLs of reference: %v" , err )
}
}
if len ( ref . Annotations ) > 0 {
r . Annotations = map [ string ] string { }
if err := json . Unmarshal ( [ ] byte ( ref . Annotations ) , & r . Annotations ) ; err != nil {
log . Errorf ( "failed to unmarshal the annotations of reference: %v" , err )
}
}
2019-12-04 09:55:41 +01:00
}
2019-12-13 01:49:45 +01:00
// To converts the reference to data level object
func ( r * Reference ) To ( ) * dao . ArtifactReference {
ref := & dao . ArtifactReference {
2020-03-05 03:54:45 +01:00
ID : r . ID ,
ParentID : r . ParentID ,
ChildID : r . ChildID ,
ChildDigest : r . ChildDigest ,
2019-12-13 01:49:45 +01:00
}
if r . Platform != nil {
platform , err := json . Marshal ( r . Platform )
if err != nil {
log . Errorf ( "failed to marshal the platform of reference: %v" , err )
}
ref . Platform = string ( platform )
2019-12-04 09:55:41 +01:00
}
2020-03-05 03:54:45 +01:00
if len ( r . URLs ) > 0 {
urls , err := json . Marshal ( r . URLs )
if err != nil {
log . Errorf ( "failed to marshal the URLs of reference: %v" , err )
}
ref . URLs = string ( urls )
}
if len ( r . Annotations ) > 0 {
annotations , err := json . Marshal ( r . Annotations )
if err != nil {
log . Errorf ( "failed to marshal the annotations of reference: %v" , err )
}
ref . Annotations = string ( annotations )
}
2019-12-13 01:49:45 +01:00
return ref
2019-12-04 09:55:41 +01:00
}
2020-03-05 07:26:53 +01:00
// ToSwagger converts the reference to the swagger model
func ( r * Reference ) ToSwagger ( ) * models . Reference {
ref := & models . Reference {
ChildDigest : r . ChildDigest ,
ChildID : r . ChildID ,
ParentID : r . ParentID ,
Annotations : r . Annotations ,
Urls : r . URLs ,
}
if r . Platform != nil {
ref . Platform = & models . Platform {
Architecture : r . Platform . Architecture ,
Os : r . Platform . OS ,
OsFeatures : r . Platform . OSFeatures ,
OsVersion : r . Platform . OSVersion ,
Variant : r . Platform . Variant ,
}
}
return ref
}