replace subject id with digest (#18278)

Since it has to support push subject and accessories in either order, it has to replace digest with id

Signed-off-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
Wang Yan 2023-03-08 17:03:12 +08:00 committed by GitHub
parent fecee37439
commit 295260b7a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 198 additions and 182 deletions

View File

@ -9382,10 +9382,9 @@ definitions:
format: int64 format: int64
description: The artifact id of the accessory description: The artifact id of the accessory
x-omitempty: false x-omitempty: false
subject_artifact_id: subject_artifact_digest:
type: integer type: string
format: int64 description: The subject artifact digest of the accessory
description: The subject artifact id of the accessory
x-omitempty: false x-omitempty: false
size: size:
type: integer type: integer

View File

@ -1,5 +1,26 @@
/* remove the redundant data from table artifact_blob */ /* remove the redundant data from table artifact_blob */
delete from artifact_blob afb where not exists (select digest from blob b where b.digest = afb.digest_af); delete from artifact_blob afb where not exists (select digest from blob b where b.digest = afb.digest_af);
/* replace subject_artifact_id with subject_artifact_digest*/
alter table artifact_accessory add column subject_artifact_digest varchar(1024);
DO $$
DECLARE
acc RECORD;
art RECORD;
BEGIN
FOR acc IN SELECT * FROM artifact_accessory
LOOP
SELECT * INTO art from artifact where id = acc.subject_artifact_id;
UPDATE artifact_accessory SET subject_artifact_digest=art.digest WHERE subject_artifact_id = art.id;
END LOOP;
END $$;
alter table artifact_accessory drop CONSTRAINT artifact_accessory_subject_artifact_id_fkey;
alter table artifact_accessory drop CONSTRAINT unique_artifact_accessory;
alter table artifact_accessory add CONSTRAINT unique_artifact_accessory UNIQUE (artifact_id, subject_artifact_digest);
alter table artifact_accessory drop column subject_artifact_id;
/* Update the registry and replication policy associated with the chartmuseum */ /* Update the registry and replication policy associated with the chartmuseum */
UPDATE registry UPDATE registry
SET description = 'Chartmuseum has been deprecated in Harbor v2.8.0, please delete this registry.' SET description = 'Chartmuseum has been deprecated in Harbor v2.8.0, please delete this registry.'

View File

@ -161,7 +161,7 @@ func (c *controller) Ensure(ctx context.Context, repository, digest string, opti
} }
} }
for _, acc := range option.Accs { for _, acc := range option.Accs {
if err = c.accessoryMgr.Ensure(ctx, artifact.ID, acc.ArtifactID, acc.Size, acc.Digest, acc.Type); err != nil { if err = c.accessoryMgr.Ensure(ctx, artifact.Digest, acc.ArtifactID, acc.Size, acc.Digest, acc.Type); err != nil {
return false, 0, err return false, 0, err
} }
} }
@ -722,7 +722,7 @@ func (c *controller) populateAdditionLinks(ctx context.Context, artifact *Artifa
} }
func (c *controller) populateAccessories(ctx context.Context, art *Artifact) { func (c *controller) populateAccessories(ctx context.Context, art *Artifact) {
accs, err := c.accessoryMgr.List(ctx, q.New(q.KeyWords{"SubjectArtifactID": art.ID})) accs, err := c.accessoryMgr.List(ctx, q.New(q.KeyWords{"SubjectArtifactDigest": art.Digest}))
if err != nil { if err != nil {
log.Errorf("failed to list accessories of artifact %d: %v", art.ID, err) log.Errorf("failed to list accessories of artifact %d: %v", art.ID, err)
return return

View File

@ -137,10 +137,10 @@ func (c *controllerTestSuite) TestAssembleArtifact() {
}, nil) }, nil)
acc := &basemodel.Default{ acc := &basemodel.Default{
Data: accessorymodel.AccessoryData{ Data: accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: 2, ArtifactID: 2,
SubArtifactID: 1, SubArtifactDigest: "sha256:123",
Type: accessorymodel.TypeCosignSignature, Type: accessorymodel.TypeCosignSignature,
}, },
} }
c.accMgr.On("List", mock.Anything, mock.Anything).Return([]accessorymodel.Accessory{ c.accMgr.On("List", mock.Anything, mock.Anything).Return([]accessorymodel.Accessory{
@ -546,10 +546,10 @@ func (c *controllerTestSuite) TestCopy() {
}, nil) }, nil)
acc := &basemodel.Default{ acc := &basemodel.Default{
Data: accessorymodel.AccessoryData{ Data: accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: 2, ArtifactID: 2,
SubArtifactID: 1, SubArtifactDigest: "sha256:418fb88ec412e340cdbef913b8ca1bbe8f9e8dc705f9617414c1f2c8db980180",
Type: accessorymodel.TypeCosignSignature, Type: accessorymodel.TypeCosignSignature,
}, },
} }
c.accMgr.On("List", mock.Anything, mock.Anything).Return([]accessorymodel.Accessory{ c.accMgr.On("List", mock.Anything, mock.Anything).Return([]accessorymodel.Accessory{

View File

@ -10,7 +10,7 @@ import (
) )
func TestUnmarshalJSONWithACC(t *testing.T) { func TestUnmarshalJSONWithACC(t *testing.T) {
data := []byte(`[{"accessories":[{"artifact_id":9,"creation_time":"2022-01-20T09:18:50.993Z","digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","icon":"","id":4,"size":501,"subject_artifact_id":8,"type":"signature.cosign"}], data := []byte(`[{"accessories":[{"artifact_id":9,"creation_time":"2022-01-20T09:18:50.993Z","digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","icon":"","id":4,"size":501,"subject_artifact_digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c","type":"signature.cosign"}],
"addition_links":{"build_history":{"absolute":false,"href":"/api/v2.0/projects/source_project011642670285/repositories/redis/artifacts/sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c/additions/build_history"}, "addition_links":{"build_history":{"absolute":false,"href":"/api/v2.0/projects/source_project011642670285/repositories/redis/artifacts/sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c/additions/build_history"},
"vulnerabilities":{"absolute":false,"href":"/api/v2.0/projects/source_project011642670285/repositories/redis/artifacts/sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c/additions/vulnerabilities"}}, "vulnerabilities":{"absolute":false,"href":"/api/v2.0/projects/source_project011642670285/repositories/redis/artifacts/sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c/additions/vulnerabilities"}},
"digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c", "digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c",
@ -31,7 +31,7 @@ func TestUnmarshalJSONWithACC(t *testing.T) {
} }
func TestUnmarshalJSONWithACCPartial(t *testing.T) { func TestUnmarshalJSONWithACCPartial(t *testing.T) {
data := []byte(`[{"accessories":[{"artifact_id":9,"creation_time":"2022-01-20T09:18:50.993Z","digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","icon":"","id":4,"size":501,"subject_artifact_id":8,"type":"signature.cosign"}, {"artifact_id":2, "type":"signature.cosign"}], data := []byte(`[{"accessories":[{"artifact_id":9,"creation_time":"2022-01-20T09:18:50.993Z","digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","icon":"","id":4,"size":501,"subject_artifact_digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","type":"signature.cosign"}, {"artifact_id":2, "type":"signature.cosign"}],
"digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c","tags":[{"artifact_id":8,"id":6,"immutable":false,"name":"latest","pull_time":"2022-01-20T09:18:50.783Z","push_time":"2022-01-20T09:18:50.303Z","repository_id":5,"signed":false}],"type":"IMAGE"}]`) "digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c","tags":[{"artifact_id":8,"id":6,"immutable":false,"name":"latest","pull_time":"2022-01-20T09:18:50.783Z","push_time":"2022-01-20T09:18:50.303Z","repository_id":5,"signed":false}],"type":"IMAGE"}]`)
var artifact []Artifact var artifact []Artifact
@ -47,7 +47,7 @@ func TestUnmarshalJSONWithACCPartial(t *testing.T) {
} }
func TestUnmarshalJSONWithACCUnknownType(t *testing.T) { func TestUnmarshalJSONWithACCUnknownType(t *testing.T) {
data := []byte(`[{"accessories":[{"artifact_id":9,"creation_time":"2022-01-20T09:18:50.993Z","digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","icon":"","id":4,"size":501,"subject_artifact_id":8}], data := []byte(`[{"accessories":[{"artifact_id":9,"creation_time":"2022-01-20T09:18:50.993Z","digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3","icon":"","id":4,"size":501,"subject_artifact_digest":"sha256:a7caa2636af890178a0b8c4cdbc47ced4dbdf29a1680e9e50823e85ce35b28d3"}],
"digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c","tags":[{"artifact_id":8,"id":6,"immutable":false,"name":"latest","pull_time":"2022-01-20T09:18:50.783Z","push_time":"2022-01-20T09:18:50.303Z","repository_id":5,"signed":false}],"type":"IMAGE"}]`) "digest":"sha256:e4b315ad03a1d1d9ff0c111e648a1a91066c09ead8352d3d6a48fa971a82922c","tags":[{"artifact_id":8,"id":6,"immutable":false,"name":"latest","pull_time":"2022-01-20T09:18:50.783Z","push_time":"2022-01-20T09:18:50.303Z","repository_id":5,"signed":false}],"type":"IMAGE"}]`)
var artifact []Artifact var artifact []Artifact

View File

@ -95,11 +95,11 @@ func (d *dao) Create(ctx context.Context, acc *Accessory) (int64, error) {
} }
id, err := ormer.Insert(acc) id, err := ormer.Insert(acc)
if err != nil { if err != nil {
if e := orm.AsConflictError(err, "accessory %s already exists under the artifact %d", if e := orm.AsConflictError(err, "accessory %s already exists under the artifact %s",
acc.Digest, acc.SubjectArtifactID); e != nil { acc.Digest, acc.SubjectArtifactDigest); e != nil {
err = e err = e
} else if e := orm.AsForeignKeyError(err, "the accessory %s tries to attach to a non existing artifact %d", } else if e := orm.AsForeignKeyError(err, "the accessory %s tries to attach to a non existing artifact %s",
acc.Digest, acc.SubjectArtifactID); e != nil { acc.Digest, acc.SubjectArtifactDigest); e != nil {
err = e err = e
} }
} }

View File

@ -32,12 +32,13 @@ import (
type daoTestSuite struct { type daoTestSuite struct {
htesting.Suite htesting.Suite
dao DAO dao DAO
artDAO artdao.DAO artDAO artdao.DAO
artifactID int64 artifactID int64
subArtifactID int64 subArtifactID int64
accID int64 subArtifactDigest string
ctx context.Context accID int64
ctx context.Context
} }
func (d *daoTestSuite) SetupSuite() { func (d *daoTestSuite) SetupSuite() {
@ -47,16 +48,18 @@ func (d *daoTestSuite) SetupSuite() {
d.ClearTables = []string{"artifact", "artifact_accessory"} d.ClearTables = []string{"artifact", "artifact_accessory"}
d.artDAO = artdao.New() d.artDAO = artdao.New()
artifactID, err := d.artDAO.Create(d.ctx, &artdao.Artifact{ art := &artdao.Artifact{
Type: "IMAGE", Type: "IMAGE",
MediaType: "application/vnd.oci.image.config.v1+json", MediaType: "application/vnd.oci.image.config.v1+json",
ManifestMediaType: "application/vnd.oci.image.manifest.v1+json", ManifestMediaType: "application/vnd.oci.image.manifest.v1+json",
ProjectID: 1, ProjectID: 1,
RepositoryID: 1000, RepositoryID: 1000,
Digest: d.DigestString(), Digest: d.DigestString(),
}) }
d.Require().Nil(err) artifactID, err := d.artDAO.Create(d.ctx, art)
d.subArtifactID = artifactID d.subArtifactID = artifactID
d.Require().Nil(err)
d.subArtifactDigest = art.Digest
d.artDAO = artdao.New() d.artDAO = artdao.New()
artifactID, err = d.artDAO.Create(d.ctx, &artdao.Artifact{ artifactID, err = d.artDAO.Create(d.ctx, &artdao.Artifact{
@ -71,11 +74,11 @@ func (d *daoTestSuite) SetupSuite() {
d.artifactID = artifactID d.artifactID = artifactID
accID, err := d.dao.Create(d.ctx, &Accessory{ accID, err := d.dao.Create(d.ctx, &Accessory{
ArtifactID: d.artifactID, ArtifactID: d.artifactID,
SubjectArtifactID: d.subArtifactID, SubjectArtifactDigest: d.subArtifactDigest,
Digest: d.DigestString(), Digest: d.DigestString(),
Size: 1234, Size: 1234,
Type: "cosign.signature", Type: "cosign.signature",
}) })
d.Require().Nil(err) d.Require().Nil(err)
d.accID = accID d.accID = accID
@ -103,7 +106,7 @@ func (d *daoTestSuite) TestCount() {
d.True(total > 0) d.True(total > 0)
total, err = d.dao.Count(d.ctx, &q.Query{ total, err = d.dao.Count(d.ctx, &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": d.subArtifactID, "SubjectArtifactDigest": d.subArtifactDigest,
}, },
}) })
d.Require().Nil(err) d.Require().Nil(err)
@ -125,7 +128,7 @@ func (d *daoTestSuite) TestList() {
accs, err = d.dao.List(d.ctx, &q.Query{ accs, err = d.dao.List(d.ctx, &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": d.subArtifactID, "SubjectArtifactDigest": d.subArtifactDigest,
}, },
}) })
d.Require().Nil(err) d.Require().Nil(err)
@ -149,27 +152,15 @@ func (d *daoTestSuite) TestCreate() {
// conflict // conflict
acc := &Accessory{ acc := &Accessory{
ArtifactID: d.artifactID, ArtifactID: d.artifactID,
SubjectArtifactID: d.subArtifactID, SubjectArtifactDigest: d.subArtifactDigest,
Digest: d.DigestString(), Digest: d.DigestString(),
Size: 1234, Size: 1234,
Type: "cosign.signature", Type: "cosign.signature",
} }
_, err := d.dao.Create(d.ctx, acc) _, err := d.dao.Create(d.ctx, acc)
d.Require().NotNil(err) d.Require().NotNil(err)
d.True(errors.IsErr(err, errors.ConflictCode)) d.True(errors.IsErr(err, errors.ConflictCode))
// violating foreign key constraint: the artifact that the tag tries to attach doesn't exist
acc = &Accessory{
ArtifactID: 999,
SubjectArtifactID: 998,
Digest: d.DigestString(),
Size: 1234,
Type: "cosign.signature",
}
_, err = d.dao.Create(d.ctx, acc)
d.Require().NotNil(err)
d.True(errors.IsErr(err, errors.ViolateForeignKeyConstraintCode))
} }
func (d *daoTestSuite) TestDelete() { func (d *daoTestSuite) TestDelete() {
@ -184,14 +175,15 @@ func (d *daoTestSuite) TestDelete() {
} }
func (d *daoTestSuite) TestDeleteOfArtifact() { func (d *daoTestSuite) TestDeleteOfArtifact() {
subArtID, err := d.artDAO.Create(d.ctx, &artdao.Artifact{ art := &artdao.Artifact{
Type: "IMAGE", Type: "IMAGE",
MediaType: "application/vnd.oci.image.config.v1+json", MediaType: "application/vnd.oci.image.config.v1+json",
ManifestMediaType: "application/vnd.oci.image.manifest.v1+json", ManifestMediaType: "application/vnd.oci.image.manifest.v1+json",
ProjectID: 1, ProjectID: 1,
RepositoryID: 1000, RepositoryID: 1000,
Digest: d.DigestString(), Digest: d.DigestString(),
}) }
subArtID, err := d.artDAO.Create(d.ctx, art)
d.Require().Nil(err) d.Require().Nil(err)
defer d.artDAO.Delete(d.ctx, subArtID) defer d.artDAO.Delete(d.ctx, subArtID)
@ -218,28 +210,28 @@ func (d *daoTestSuite) TestDeleteOfArtifact() {
defer d.artDAO.Delete(d.ctx, artID2) defer d.artDAO.Delete(d.ctx, artID2)
acc1 := &Accessory{ acc1 := &Accessory{
ArtifactID: artID1, ArtifactID: artID1,
SubjectArtifactID: subArtID, SubjectArtifactDigest: art.Digest,
Digest: d.DigestString(), Digest: d.DigestString(),
Size: 1234, Size: 1234,
Type: "cosign.signature", Type: "cosign.signature",
} }
_, err = d.dao.Create(d.ctx, acc1) _, err = d.dao.Create(d.ctx, acc1)
d.Require().Nil(err) d.Require().Nil(err)
acc2 := &Accessory{ acc2 := &Accessory{
ArtifactID: artID2, ArtifactID: artID2,
SubjectArtifactID: subArtID, SubjectArtifactDigest: art.Digest,
Digest: d.DigestString(), Digest: d.DigestString(),
Size: 1234, Size: 1234,
Type: "cosign.signature", Type: "cosign.signature",
} }
_, err = d.dao.Create(d.ctx, acc2) _, err = d.dao.Create(d.ctx, acc2)
d.Require().Nil(err) d.Require().Nil(err)
accs, err := d.dao.List(d.ctx, &q.Query{ accs, err := d.dao.List(d.ctx, &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": subArtID, "SubjectArtifactDigest": art.Digest,
}, },
}) })
for _, acc := range accs { for _, acc := range accs {
@ -250,14 +242,14 @@ func (d *daoTestSuite) TestDeleteOfArtifact() {
_, err = d.dao.DeleteAccessories(d.ctx, &q.Query{ _, err = d.dao.DeleteAccessories(d.ctx, &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": subArtID, "SubjectArtifactDigest": art.Digest,
}, },
}) })
d.Require().Nil(err) d.Require().Nil(err)
accs, err = d.dao.List(d.ctx, &q.Query{ accs, err = d.dao.List(d.ctx, &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": subArtID, "SubjectArtifactDigest": art.Digest,
}, },
}) })
d.Require().Nil(err) d.Require().Nil(err)

View File

@ -26,13 +26,13 @@ func init() {
// Accessory model in database // Accessory model in database
type Accessory struct { type Accessory struct {
ID int64 `orm:"pk;auto;column(id)" json:"id"` ID int64 `orm:"pk;auto;column(id)" json:"id"`
ArtifactID int64 `orm:"column(artifact_id)" json:"artifact_id"` ArtifactID int64 `orm:"column(artifact_id)" json:"artifact_id"`
SubjectArtifactID int64 `orm:"column(subject_artifact_id)" json:"subject_artifact_id"` SubjectArtifactDigest string `orm:"column(subject_artifact_digest)" json:"subject_artifact_digest"`
Type string `orm:"column(type)" json:"type"` Type string `orm:"column(type)" json:"type"`
Size int64 `orm:"column(size)" json:"size"` Size int64 `orm:"column(size)" json:"size"`
Digest string `orm:"column(digest)" json:"digest"` Digest string `orm:"column(digest)" json:"digest"`
CreationTime time.Time `orm:"column(creation_time);auto_now_add" json:"creation_time"` CreationTime time.Time `orm:"column(creation_time);auto_now_add" json:"creation_time"`
} }
// TableName for artifact reference // TableName for artifact reference

View File

@ -38,7 +38,7 @@ var (
// Manager is the only interface of artifact module to provide the management functions for artifacts // Manager is the only interface of artifact module to provide the management functions for artifacts
type Manager interface { type Manager interface {
// Ensure ... // Ensure ...
Ensure(ctx context.Context, subArtID, artifactID, size int64, digest, accType string) error Ensure(ctx context.Context, subArtDigest string, artifactID, size int64, digest, accType string) error
// Get the artifact specified by the ID // Get the artifact specified by the ID
Get(ctx context.Context, id int64) (accessory model.Accessory, err error) Get(ctx context.Context, id int64) (accessory model.Accessory, err error)
// Count returns the total count of accessory according to the query. // Count returns the total count of accessory according to the query.
@ -66,7 +66,7 @@ type manager struct {
dao dao.DAO dao dao.DAO
} }
func (m *manager) Ensure(ctx context.Context, subArtID, artifactID, size int64, digest, accType string) error { func (m *manager) Ensure(ctx context.Context, subArtDigest string, artifactID, size int64, digest, accType string) error {
accs, err := m.dao.List(ctx, q.New(q.KeyWords{"ArtifactID": artifactID, "Digest": digest})) accs, err := m.dao.List(ctx, q.New(q.KeyWords{"ArtifactID": artifactID, "Digest": digest}))
if err != nil { if err != nil {
return err return err
@ -76,11 +76,11 @@ func (m *manager) Ensure(ctx context.Context, subArtID, artifactID, size int64,
} }
acc := model.AccessoryData{ acc := model.AccessoryData{
ArtifactID: artifactID, ArtifactID: artifactID,
SubArtifactID: subArtID, SubArtifactDigest: subArtDigest,
Digest: digest, Digest: digest,
Size: size, Size: size,
Type: accType, Type: accType,
} }
_, err = m.Create(ctx, acc) _, err = m.Create(ctx, acc)
return err return err
@ -92,13 +92,13 @@ func (m *manager) Get(ctx context.Context, id int64) (model.Accessory, error) {
return nil, err return nil, err
} }
return model.New(acc.Type, model.AccessoryData{ return model.New(acc.Type, model.AccessoryData{
ID: acc.ID, ID: acc.ID,
ArtifactID: acc.ArtifactID, ArtifactID: acc.ArtifactID,
SubArtifactID: acc.SubjectArtifactID, SubArtifactDigest: acc.SubjectArtifactDigest,
Size: acc.Size, Size: acc.Size,
Digest: acc.Digest, Digest: acc.Digest,
CreatTime: acc.CreationTime, CreatTime: acc.CreationTime,
Icon: m.GetIcon(acc.Type), Icon: m.GetIcon(acc.Type),
}) })
} }
@ -114,13 +114,13 @@ func (m *manager) List(ctx context.Context, query *q.Query) ([]model.Accessory,
var accs []model.Accessory var accs []model.Accessory
for _, accD := range accsDao { for _, accD := range accsDao {
acc, err := model.New(accD.Type, model.AccessoryData{ acc, err := model.New(accD.Type, model.AccessoryData{
ID: accD.ID, ID: accD.ID,
ArtifactID: accD.ArtifactID, ArtifactID: accD.ArtifactID,
SubArtifactID: accD.SubjectArtifactID, SubArtifactDigest: accD.SubjectArtifactDigest,
Size: accD.Size, Size: accD.Size,
Digest: accD.Digest, Digest: accD.Digest,
CreatTime: accD.CreationTime, CreatTime: accD.CreationTime,
Icon: m.GetIcon(accD.Type), Icon: m.GetIcon(accD.Type),
}) })
if err != nil { if err != nil {
return nil, errors.New(err).WithCode(errors.BadRequestCode) return nil, errors.New(err).WithCode(errors.BadRequestCode)
@ -132,11 +132,11 @@ func (m *manager) List(ctx context.Context, query *q.Query) ([]model.Accessory,
func (m *manager) Create(ctx context.Context, accessory model.AccessoryData) (int64, error) { func (m *manager) Create(ctx context.Context, accessory model.AccessoryData) (int64, error) {
acc := &dao.Accessory{ acc := &dao.Accessory{
ArtifactID: accessory.ArtifactID, ArtifactID: accessory.ArtifactID,
SubjectArtifactID: accessory.SubArtifactID, SubjectArtifactDigest: accessory.SubArtifactDigest,
Size: accessory.Size, Size: accessory.Size,
Digest: accessory.Digest, Digest: accessory.Digest,
Type: accessory.Type, Type: accessory.Type,
} }
return m.dao.Create(ctx, acc) return m.dao.Create(ctx, acc)
} }

View File

@ -45,7 +45,7 @@ func (m *managerTestSuite) SetupTest() {
func (m *managerTestSuite) TestEnsure() { func (m *managerTestSuite) TestEnsure() {
mock.OnAnything(m.dao, "List").Return([]*dao.Accessory{}, nil) mock.OnAnything(m.dao, "List").Return([]*dao.Accessory{}, nil)
mock.OnAnything(m.dao, "Create").Return(int64(1), nil) mock.OnAnything(m.dao, "Create").Return(int64(1), nil)
err := m.mgr.Ensure(nil, int64(1), int64(1), int64(1), "sha256:1234", model.TypeCosignSignature) err := m.mgr.Ensure(nil, string(""), int64(1), int64(1), "sha256:1234", model.TypeCosignSignature)
m.Require().Nil(err) m.Require().Nil(err)
} }

View File

@ -73,14 +73,14 @@ const (
// AccessoryData ... // AccessoryData ...
type AccessoryData struct { type AccessoryData struct {
ID int64 `json:"id"` ID int64 `json:"id"`
ArtifactID int64 `json:"artifact_id"` ArtifactID int64 `json:"artifact_id"`
SubArtifactID int64 `json:"subject_artifact_id"` SubArtifactDigest string `json:"subject_artifact_id"`
Type string `json:"type"` Type string `json:"type"`
Size int64 `json:"size"` Size int64 `json:"size"`
Digest string `json:"digest"` Digest string `json:"digest"`
CreatTime time.Time `json:"creation_time"` CreatTime time.Time `json:"creation_time"`
Icon string `json:"icon"` Icon string `json:"icon"`
} }
// Accessory Independent, but linked to an existing subject artifact, which enabling the extensibility of an OCI artifact // Accessory Independent, but linked to an existing subject artifact, which enabling the extensibility of an OCI artifact

View File

@ -21,10 +21,10 @@ func (suite *BaseTestSuite) SetupSuite() {
suite.subDigest = suite.DigestString() suite.subDigest = suite.DigestString()
suite.accessory, _ = model.New(model.TypeNone, suite.accessory, _ = model.New(model.TypeNone,
model.AccessoryData{ model.AccessoryData{
ArtifactID: 1, ArtifactID: 1,
SubArtifactID: 2, SubArtifactDigest: suite.subDigest,
Size: 1234, Size: 1234,
Digest: suite.digest, Digest: suite.digest,
}) })
} }
@ -37,7 +37,7 @@ func (suite *BaseTestSuite) TestGetArtID() {
} }
func (suite *BaseTestSuite) TestSubGetArtID() { func (suite *BaseTestSuite) TestSubGetArtID() {
suite.Equal(int64(2), suite.accessory.GetData().SubArtifactID) suite.Equal(suite.subDigest, suite.accessory.GetData().SubArtifactDigest)
} }
func (suite *BaseTestSuite) TestSubGetSize() { func (suite *BaseTestSuite) TestSubGetSize() {

View File

@ -13,16 +13,18 @@ type CosignTestSuite struct {
htesting.Suite htesting.Suite
accessory model.Accessory accessory model.Accessory
digest string digest string
subDigest string
} }
func (suite *CosignTestSuite) SetupSuite() { func (suite *CosignTestSuite) SetupSuite() {
suite.digest = suite.DigestString() suite.digest = suite.DigestString()
suite.subDigest = suite.DigestString()
suite.accessory, _ = model.New(model.TypeCosignSignature, suite.accessory, _ = model.New(model.TypeCosignSignature,
model.AccessoryData{ model.AccessoryData{
ArtifactID: 1, ArtifactID: 1,
SubArtifactID: 2, SubArtifactDigest: suite.subDigest,
Size: 4321, Size: 4321,
Digest: suite.digest, Digest: suite.digest,
}) })
} }
@ -35,7 +37,7 @@ func (suite *CosignTestSuite) TestGetArtID() {
} }
func (suite *CosignTestSuite) TestSubGetArtID() { func (suite *CosignTestSuite) TestSubGetArtID() {
suite.Equal(int64(2), suite.accessory.GetData().SubArtifactID) suite.Equal(suite.subDigest, suite.accessory.GetData().SubArtifactDigest)
} }
func (suite *CosignTestSuite) TestSubGetSize() { func (suite *CosignTestSuite) TestSubGetSize() {

View File

@ -13,16 +13,18 @@ type NydusTestSuite struct {
htesting.Suite htesting.Suite
accessory model.Accessory accessory model.Accessory
digest string digest string
subDigest string
} }
func (suite *NydusTestSuite) SetupSuite() { func (suite *NydusTestSuite) SetupSuite() {
suite.digest = suite.DigestString() suite.digest = suite.DigestString()
suite.subDigest = suite.DigestString()
suite.accessory, _ = model.New(model.TypeNydusAccelerator, suite.accessory, _ = model.New(model.TypeNydusAccelerator,
model.AccessoryData{ model.AccessoryData{
ArtifactID: 1, ArtifactID: 1,
SubArtifactID: 2, SubArtifactDigest: suite.subDigest,
Size: 4321, Size: 4321,
Digest: suite.digest, Digest: suite.digest,
}) })
} }
@ -35,7 +37,7 @@ func (suite *NydusTestSuite) TestGetArtID() {
} }
func (suite *NydusTestSuite) TestSubGetArtID() { func (suite *NydusTestSuite) TestSubGetArtID() {
suite.Equal(int64(2), suite.accessory.GetData().SubArtifactID) suite.Equal(suite.subDigest, suite.accessory.GetData().SubArtifactDigest)
} }
func (suite *NydusTestSuite) TestSubGetSize() { func (suite *NydusTestSuite) TestSubGetSize() {

View File

@ -227,10 +227,10 @@ func (suite *CosignMiddlewareTestSuite) TestSignaturePulling() {
mock.OnAnything(suite.projectController, "GetByName").Return(suite.project, nil) mock.OnAnything(suite.projectController, "GetByName").Return(suite.project, nil)
acc := &basemodel.Default{ acc := &basemodel.Default{
Data: accessorymodel.AccessoryData{ Data: accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: 2, ArtifactID: 2,
SubArtifactID: 1, SubArtifactDigest: suite.artifact.Digest,
Type: accessorymodel.TypeCosignSignature, Type: accessorymodel.TypeCosignSignature,
}, },
} }
mock.OnAnything(suite.accessMgr, "List").Return([]accessorymodel.Accessory{ mock.OnAnything(suite.accessMgr, "List").Return([]accessorymodel.Accessory{

View File

@ -210,10 +210,10 @@ func (suite *MiddlewareTestSuite) TestSignaturePulling() {
mock.OnAnything(suite.projectController, "GetByName").Return(suite.project, nil) mock.OnAnything(suite.projectController, "GetByName").Return(suite.project, nil)
acc := &basemodel.Default{ acc := &basemodel.Default{
Data: accessorymodel.AccessoryData{ Data: accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: 2, ArtifactID: 2,
SubArtifactID: 1, SubArtifactDigest: suite.artifact.Digest,
Type: accessorymodel.TypeCosignSignature, Type: accessorymodel.TypeCosignSignature,
}, },
} }
mock.OnAnything(suite.accessMgr, "List").Return([]accessorymodel.Accessory{ mock.OnAnything(suite.accessMgr, "List").Return([]accessorymodel.Accessory{

View File

@ -110,11 +110,11 @@ func SignatureMiddleware() func(http.Handler) http.Handler {
if err := orm.WithTransaction(func(ctx context.Context) error { if err := orm.WithTransaction(func(ctx context.Context) error {
_, err := accessory.Mgr.Create(ctx, model.AccessoryData{ _, err := accessory.Mgr.Create(ctx, model.AccessoryData{
ArtifactID: art.ID, ArtifactID: art.ID,
SubArtifactID: subjectArt.ID, SubArtifactDigest: subjectArt.Digest,
Size: desc.Size, Size: desc.Size,
Digest: desc.Digest.String(), Digest: desc.Digest.String(),
Type: model.TypeCosignSignature, Type: model.TypeCosignSignature,
}) })
return err return err
})(orm.SetTransactionOpNameToContext(ctx, "tx-create-cosign-accessory")); err != nil { })(orm.SetTransactionOpNameToContext(ctx, "tx-create-cosign-accessory")); err != nil {

View File

@ -15,8 +15,8 @@ import (
"github.com/goharbor/harbor/src/lib/q" "github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg" "github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/accessory" "github.com/goharbor/harbor/src/pkg/accessory"
accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model"
"github.com/goharbor/harbor/src/pkg/accessory/model" "github.com/goharbor/harbor/src/pkg/accessory/model"
accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model"
_ "github.com/goharbor/harbor/src/pkg/accessory/model/base" _ "github.com/goharbor/harbor/src/pkg/accessory/model/base"
_ "github.com/goharbor/harbor/src/pkg/accessory/model/cosign" _ "github.com/goharbor/harbor/src/pkg/accessory/model/cosign"
"github.com/goharbor/harbor/src/pkg/artifact" "github.com/goharbor/harbor/src/pkg/artifact"
@ -98,7 +98,7 @@ func (suite *MiddlewareTestSuite) addArtAcc(pid, repositoryID int64, repositoryN
PushTime: time.Now(), PushTime: time.Now(),
PullTime: time.Now(), PullTime: time.Now(),
} }
subafid, err := pkg.ArtifactMgr.Create(suite.Context(), subaf) _, err := pkg.ArtifactMgr.Create(suite.Context(), subaf)
suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID))
af := &artifact.Artifact{ af := &artifact.Artifact{
@ -115,11 +115,11 @@ func (suite *MiddlewareTestSuite) addArtAcc(pid, repositoryID int64, repositoryN
suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID))
accid, err := accessory.Mgr.Create(suite.Context(), accessorymodel.AccessoryData{ accid, err := accessory.Mgr.Create(suite.Context(), accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: afid, ArtifactID: afid,
SubArtifactID: subafid, SubArtifactDigest: subaf.Digest,
Digest: accdgt, Digest: accdgt,
Type: accessorymodel.TypeCosignSignature, Type: accessorymodel.TypeCosignSignature,
}) })
suite.Nil(err, fmt.Sprintf("Add artifact accesspry failed for %d", repositoryID)) suite.Nil(err, fmt.Sprintf("Add artifact accesspry failed for %d", repositoryID))
return accid return accid
@ -134,7 +134,7 @@ func (suite *MiddlewareTestSuite) TestCosignSignature() {
_, repoId, err := repository.Ctl.Ensure(suite.Context(), name) _, repoId, err := repository.Ctl.Ensure(suite.Context(), name)
suite.Nil(err) suite.Nil(err)
subjectArtID := suite.addArt(projectID, repoId, name, subArtDigest) suite.addArt(projectID, repoId, name, subArtDigest)
artID := suite.addArt(projectID, repoId, name, descriptor.Digest.String()) artID := suite.addArt(projectID, repoId, name, descriptor.Digest.String())
suite.Nil(err) suite.Nil(err)
@ -145,11 +145,11 @@ func (suite *MiddlewareTestSuite) TestCosignSignature() {
accs, err := accessory.Mgr.List(suite.Context(), &q.Query{ accs, err := accessory.Mgr.List(suite.Context(), &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": subjectArtID, "SubjectArtifactDigest": subArtDigest,
}, },
}) })
suite.Equal(1, len(accs)) suite.Equal(1, len(accs))
suite.Equal(subjectArtID, accs[0].GetData().SubArtifactID) suite.Equal(subArtDigest, accs[0].GetData().SubArtifactDigest)
suite.Equal(artID, accs[0].GetData().ArtifactID) suite.Equal(artID, accs[0].GetData().ArtifactID)
suite.True(accs[0].IsHard()) suite.True(accs[0].IsHard())
suite.Equal(model.TypeCosignSignature, accs[0].GetData().Type) suite.Equal(model.TypeCosignSignature, accs[0].GetData().Type)

View File

@ -129,11 +129,11 @@ func AcceleratorMiddleware() func(http.Handler) http.Handler {
if err := orm.WithTransaction(func(ctx context.Context) error { if err := orm.WithTransaction(func(ctx context.Context) error {
id, err := accessory.Mgr.Create(ctx, model.AccessoryData{ id, err := accessory.Mgr.Create(ctx, model.AccessoryData{
ArtifactID: art.ID, ArtifactID: art.ID,
SubArtifactID: subjectArt.ID, SubArtifactDigest: subjectArt.Digest,
Size: desc.Size, Size: desc.Size,
Digest: desc.Digest.String(), Digest: desc.Digest.String(),
Type: model.TypeNydusAccelerator, Type: model.TypeNydusAccelerator,
}) })
log.Debug("accessory id:", id) log.Debug("accessory id:", id)
return err return err

View File

@ -15,8 +15,8 @@ import (
"github.com/goharbor/harbor/src/lib/q" "github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg" "github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/accessory" "github.com/goharbor/harbor/src/pkg/accessory"
accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model"
"github.com/goharbor/harbor/src/pkg/accessory/model" "github.com/goharbor/harbor/src/pkg/accessory/model"
accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model"
_ "github.com/goharbor/harbor/src/pkg/accessory/model/base" _ "github.com/goharbor/harbor/src/pkg/accessory/model/base"
_ "github.com/goharbor/harbor/src/pkg/accessory/model/nydus" _ "github.com/goharbor/harbor/src/pkg/accessory/model/nydus"
"github.com/goharbor/harbor/src/pkg/artifact" "github.com/goharbor/harbor/src/pkg/artifact"
@ -114,7 +114,7 @@ func (suite *MiddlewareTestSuite) addArtAcc(pid, repositoryID int64, repositoryN
PushTime: time.Now(), PushTime: time.Now(),
PullTime: time.Now(), PullTime: time.Now(),
} }
subafid, err := pkg.ArtifactMgr.Create(suite.Context(), subaf) _, err := pkg.ArtifactMgr.Create(suite.Context(), subaf)
suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID))
af := &artifact.Artifact{ af := &artifact.Artifact{
@ -131,11 +131,11 @@ func (suite *MiddlewareTestSuite) addArtAcc(pid, repositoryID int64, repositoryN
suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID)) suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID))
accid, err := accessory.Mgr.Create(suite.Context(), accessorymodel.AccessoryData{ accid, err := accessory.Mgr.Create(suite.Context(), accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: afid, ArtifactID: afid,
SubArtifactID: subafid, SubArtifactDigest: subaf.Digest,
Digest: accdgt, Digest: accdgt,
Type: accessorymodel.TypeNydusAccelerator, Type: accessorymodel.TypeNydusAccelerator,
}) })
suite.Nil(err, fmt.Sprintf("Add artifact accesspry failed for %d", repositoryID)) suite.Nil(err, fmt.Sprintf("Add artifact accesspry failed for %d", repositoryID))
return accid return accid
@ -152,7 +152,7 @@ func (suite *MiddlewareTestSuite) TestNydusAccelerator() {
suite.Nil(err) suite.Nil(err)
// add subject artifact // add subject artifact
subjectArtID := suite.addArt(projectID, repoId, name, subArtDigest) suite.addArt(projectID, repoId, name, subArtDigest)
// add nydus artifact // add nydus artifact
artID := suite.addArt(projectID, repoId, name, descriptor.Digest.String()) artID := suite.addArt(projectID, repoId, name, descriptor.Digest.String())
@ -165,11 +165,11 @@ func (suite *MiddlewareTestSuite) TestNydusAccelerator() {
accs, _ := accessory.Mgr.List(suite.Context(), &q.Query{ accs, _ := accessory.Mgr.List(suite.Context(), &q.Query{
Keywords: map[string]interface{}{ Keywords: map[string]interface{}{
"SubjectArtifactID": subjectArtID, "SubjectArtifactDigest": subArtDigest,
}, },
}) })
suite.Equal(1, len(accs)) suite.Equal(1, len(accs))
suite.Equal(subjectArtID, accs[0].GetData().SubArtifactID) suite.Equal(subArtDigest, accs[0].GetData().SubArtifactDigest)
suite.Equal(artID, accs[0].GetData().ArtifactID) suite.Equal(artID, accs[0].GetData().ArtifactID)
suite.True(accs[0].IsHard()) suite.True(accs[0].IsHard())
suite.Equal(model.TypeNydusAccelerator, accs[0].GetData().Type) suite.Equal(model.TypeNydusAccelerator, accs[0].GetData().Type)

View File

@ -383,10 +383,10 @@ func (suite *MiddlewareTestSuite) TestSignaturePulling() {
mock.OnAnything(suite.projectController, "Get").Return(suite.project, nil) mock.OnAnything(suite.projectController, "Get").Return(suite.project, nil)
acc := &basemodel.Default{ acc := &basemodel.Default{
Data: accessorymodel.AccessoryData{ Data: accessorymodel.AccessoryData{
ID: 1, ID: 1,
ArtifactID: 2, ArtifactID: 2,
SubArtifactID: 1, SubArtifactDigest: suite.artifact.Digest,
Type: accessorymodel.TypeCosignSignature, Type: accessorymodel.TypeCosignSignature,
}, },
} }
mock.OnAnything(suite.accessMgr, "List").Return([]accessorymodel.Accessory{ mock.OnAnything(suite.accessMgr, "List").Return([]accessorymodel.Accessory{

View File

@ -372,7 +372,7 @@ func (a *artifactAPI) ListAccessories(ctx context.Context, params operation.List
if err != nil { if err != nil {
return a.SendError(ctx, err) return a.SendError(ctx, err)
} }
query.Keywords["SubjectArtifactID"] = artifact.ID query.Keywords["SubjectArtifactDigest"] = artifact.Digest
// list accessories according to the query // list accessories according to the query
total, err := a.accMgr.Count(ctx, query) total, err := a.accMgr.Count(ctx, query)

View File

@ -15,14 +15,14 @@ type Accessory struct {
// ToSwagger converts the label to the swagger model // ToSwagger converts the label to the swagger model
func (a *Accessory) ToSwagger() *models.Accessory { func (a *Accessory) ToSwagger() *models.Accessory {
return &models.Accessory{ return &models.Accessory{
ID: a.ID, ID: a.ID,
ArtifactID: a.ArtifactID, ArtifactID: a.ArtifactID,
SubjectArtifactID: a.SubArtifactID, SubjectArtifactDigest: a.SubArtifactDigest,
Size: a.Size, Size: a.Size,
Digest: a.Digest, Digest: a.Digest,
Type: a.Type, Type: a.Type,
Icon: a.Icon, Icon: a.Icon,
CreationTime: strfmt.DateTime(a.CreatTime), CreationTime: strfmt.DateTime(a.CreatTime),
} }
} }

View File

@ -86,13 +86,13 @@ func (_m *Manager) DeleteAccessories(ctx context.Context, _a1 *q.Query) error {
return r0 return r0
} }
// Ensure provides a mock function with given fields: ctx, subArtID, artifactID, size, digest, accType // Ensure provides a mock function with given fields: ctx, subArtDigest, artifactID, size, digest, accType
func (_m *Manager) Ensure(ctx context.Context, subArtID int64, artifactID int64, size int64, digest string, accType string) error { func (_m *Manager) Ensure(ctx context.Context, subArtDigest string, artifactID int64, size int64, digest string, accType string) error {
ret := _m.Called(ctx, subArtID, artifactID, size, digest, accType) ret := _m.Called(ctx, subArtDigest, artifactID, size, digest, accType)
var r0 error var r0 error
if rf, ok := ret.Get(0).(func(context.Context, int64, int64, int64, string, string) error); ok { if rf, ok := ret.Get(0).(func(context.Context, string, int64, int64, string, string) error); ok {
r0 = rf(ctx, subArtID, artifactID, size, digest, accType) r0 = rf(ctx, subArtDigest, artifactID, size, digest, accType)
} else { } else {
r0 = ret.Error(0) r0 = ret.Error(0)
} }