diff --git a/icons/cosign.png b/icons/cosign.png new file mode 100644 index 000000000..12bbb9c34 Binary files /dev/null and b/icons/cosign.png differ diff --git a/src/controller/icon/controller.go b/src/controller/icon/controller.go index 872d298ed..8baae5595 100644 --- a/src/controller/icon/controller.go +++ b/src/controller/icon/controller.go @@ -37,16 +37,37 @@ import ( ) var ( - builtInIcons = map[string]string{ - icon.DigestOfIconImage: "./icons/image.png", - icon.DigestOfIconChart: "./icons/chart.png", - icon.DigestOfIconCNAB: "./icons/cnab.png", - icon.DigestOfIconDefault: "./icons/default.png", + builtInIcons = map[string]buildInIcon{ + icon.DigestOfIconImage: { + path: "./icons/image.png", + resize: true, + }, + icon.DigestOfIconChart: { + path: "./icons/chart.png", + resize: true, + }, + icon.DigestOfIconCNAB: { + path: "./icons/cnab.png", + resize: true, + }, + icon.DigestOfIconAccCosign: { + path: "./icons/cosign.png", + resize: false, + }, + icon.DigestOfIconDefault: { + path: "./icons/default.png", + resize: true, + }, } // Ctl is a global icon controller instance Ctl = NewController() ) +type buildInIcon struct { + path string + resize bool +} + // Icon model for artifact icon type Icon struct { ContentType string @@ -84,9 +105,9 @@ func (c *controller) Get(ctx context.Context, digest string) (*Icon, error) { iconFile io.ReadCloser err error ) - // for the fixed icons: image, helm chart, CNAB and unknown - if path, exist := builtInIcons[digest]; exist { - iconFile, err = os.Open(path) + + if i, exist := builtInIcons[digest]; exist { + iconFile, err = os.Open(i.path) if err != nil { return nil, err } @@ -118,7 +139,13 @@ func (c *controller) Get(ctx context.Context, digest string) (*Icon, error) { } // resize the icon to 50x50 - img = resize.Thumbnail(50, 50, img, resize.NearestNeighbor) + if i, exist := builtInIcons[digest]; exist { + if i.resize { + img = resize.Thumbnail(50, 50, img, resize.NearestNeighbor) + } + } else { + img = resize.Thumbnail(50, 50, img, resize.NearestNeighbor) + } // encode the resized icon to png buf := &bytes.Buffer{} diff --git a/src/lib/icon/const.go b/src/lib/icon/const.go index da7330628..0c24b632a 100644 --- a/src/lib/icon/const.go +++ b/src/lib/icon/const.go @@ -9,5 +9,5 @@ const ( // ToDo add the accessories images DigestOfIconAccDefault = "" - DigestOfIconAccCosign = "" + DigestOfIconAccCosign = "sha256:20401d5b3a0f6dbc607c8d732eb08471af4ae6b19811a4efce8c6a724aed2882" ) diff --git a/src/pkg/accessory/manager.go b/src/pkg/accessory/manager.go index 44abe1db9..e0404ac09 100644 --- a/src/pkg/accessory/manager.go +++ b/src/pkg/accessory/manager.go @@ -17,6 +17,7 @@ package accessory import ( "context" "github.com/goharbor/harbor/src/lib/errors" + "github.com/goharbor/harbor/src/lib/icon" "github.com/goharbor/harbor/src/lib/q" "github.com/goharbor/harbor/src/pkg/accessory/dao" "github.com/goharbor/harbor/src/pkg/accessory/model" @@ -28,6 +29,11 @@ import ( var ( // Mgr is a global artifact manager instance Mgr = NewManager() + + // icon digests for each known type + defaultIcons = map[string]string{ + model.TypeCosignSignature: icon.DigestOfIconAccCosign, + } ) // Manager is the only interface of artifact module to provide the management functions for artifacts @@ -93,6 +99,7 @@ func (m *manager) Get(ctx context.Context, id int64) (model.Accessory, error) { Size: acc.Size, Digest: acc.Digest, CreatTime: acc.CreationTime, + Icon: m.GetIcon(acc.Type), }) } @@ -114,6 +121,7 @@ func (m *manager) List(ctx context.Context, query *q.Query) ([]model.Accessory, Size: accD.Size, Digest: accD.Digest, CreatTime: accD.CreationTime, + Icon: m.GetIcon(accD.Type), }) if err != nil { return nil, errors.New(err).WithCode(errors.BadRequestCode) @@ -142,3 +150,11 @@ func (m *manager) DeleteAccessories(ctx context.Context, q *q.Query) error { _, err := m.dao.DeleteAccessories(ctx, q) return err } + +func (m *manager) GetIcon(accType string) string { + accIcon := "" + if i, ok := defaultIcons[accType]; ok { + accIcon = i + } + return accIcon +} diff --git a/src/pkg/accessory/manager_test.go b/src/pkg/accessory/manager_test.go index 1376a7146..d3f9c03bf 100644 --- a/src/pkg/accessory/manager_test.go +++ b/src/pkg/accessory/manager_test.go @@ -104,6 +104,16 @@ func (m *managerTestSuite) TestDeleteOfArtifact() { m.dao.AssertExpectations(m.T()) } +func (m *managerTestSuite) TestGetIcon() { + var icon string + icon = m.mgr.GetIcon("") + m.Require().Empty(icon, "empty icon") + icon = m.mgr.GetIcon("signature.cosign") + m.Require().Equal("sha256:20401d5b3a0f6dbc607c8d732eb08471af4ae6b19811a4efce8c6a724aed2882", icon) + icon = m.mgr.GetIcon("unknown") + m.Require().Empty(icon, "empty icon") +} + func TestManager(t *testing.T) { suite.Run(t, &managerTestSuite{}) } diff --git a/src/pkg/accessory/model/accessory.go b/src/pkg/accessory/model/accessory.go index e21bb5b80..033d93157 100644 --- a/src/pkg/accessory/model/accessory.go +++ b/src/pkg/accessory/model/accessory.go @@ -74,6 +74,7 @@ type AccessoryData struct { Size int64 `json:"size"` Digest string `json:"digest"` CreatTime time.Time `json:"creation_time"` + Icon string `json:"icon"` } // Accessory Independent, but linked to an existing subject artifact, which enabling the extensibility of an OCI artifact diff --git a/src/server/v2.0/handler/model/accessory.go b/src/server/v2.0/handler/model/accessory.go index 24e623709..45d88c12e 100644 --- a/src/server/v2.0/handler/model/accessory.go +++ b/src/server/v2.0/handler/model/accessory.go @@ -20,7 +20,7 @@ func (a *Accessory) ToSwagger() *models.Accessory { Size: a.Size, Digest: a.Digest, Type: a.Type, - Icon: "", + Icon: a.Icon, CreationTime: strfmt.DateTime(a.CreatTime), } }