Skip to content

Commit f3bdafc

Browse files
Merge pull request #1026 from alecmerdler/bugzilla-1748771
Bug 1748771: Default Icon for PackageManifest Subresource
2 parents 39a378f + 8fede0b commit f3bdafc

File tree

2 files changed

+66
-25
lines changed

2 files changed

+66
-25
lines changed

pkg/package-server/storage/subresources.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,29 @@ func (s *LogoStorage) Connect(ctx context.Context, name string, options runtime.
4646

4747
namespace := genericreq.NamespaceValue(ctx)
4848
pkg, err := s.prov.Get(namespace, name)
49-
if err != nil || pkg == nil || len(pkg.Status.Channels) == 0 || len(pkg.Status.Channels[0].CurrentCSVDesc.Icon) == 0 {
49+
if err != nil || pkg == nil {
5050
w.WriteHeader(http.StatusNotFound)
5151
return
5252
}
53+
imgBytes, mimeType, etag := func() ([]byte, string, string) {
54+
if len(pkg.Status.Channels) == 0 || len(pkg.Status.Channels[0].CurrentCSVDesc.Icon) == 0 {
55+
return []byte(defaultIcon), "image/svg+xml", ""
56+
} else {
57+
data := pkg.Status.Channels[0].CurrentCSVDesc.Icon[0].Base64Data
58+
mimeType := pkg.Status.Channels[0].CurrentCSVDesc.Icon[0].Mediatype
59+
etag := `"` + strings.Join([]string{name, pkg.Status.Channels[0].Name, pkg.Status.Channels[0].CurrentCSV}, ".") + `"`
5360

54-
data := pkg.Status.Channels[0].CurrentCSVDesc.Icon[0].Base64Data
55-
mimeType := pkg.Status.Channels[0].CurrentCSVDesc.Icon[0].Mediatype
56-
etag := `"` + strings.Join([]string{name, pkg.Status.Channels[0].Name, pkg.Status.Channels[0].CurrentCSV}, ".") + `"`
61+
reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data))
62+
imgBytes, _ := ioutil.ReadAll(reader)
5763

58-
reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data))
59-
imgBytes, err := ioutil.ReadAll(reader)
64+
return imgBytes, mimeType, etag
65+
}
66+
}()
6067

6168
w.Header().Set("Content-Type", mimeType)
6269
w.Header().Set("Content-Length", strconv.Itoa(len(imgBytes)))
6370
w.Header().Set("Etag", etag)
64-
_, err = w.Write(imgBytes)
71+
w.Write(imgBytes)
6572
}
6673

6774
return handler, nil
@@ -90,3 +97,7 @@ func (s *LogoStorage) ProducesMIMETypes(verb string) []string {
9097
func (s *LogoStorage) ProducesObject(verb string) interface{} {
9198
return ""
9299
}
100+
101+
const defaultIcon string = `
102+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 258.51 258.51"><defs><style>.cls-1{fill:#d1d1d1;}.cls-2{fill:#8d8d8f;}</style></defs><title>Asset 4</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M129.25,20A109.1,109.1,0,0,1,206.4,206.4,109.1,109.1,0,1,1,52.11,52.11,108.45,108.45,0,0,1,129.25,20m0-20h0C58.16,0,0,58.16,0,129.25H0c0,71.09,58.16,129.26,129.25,129.26h0c71.09,0,129.26-58.17,129.26-129.26h0C258.51,58.16,200.34,0,129.25,0Z"/><path class="cls-2" d="M177.54,103.41H141.66L154.9,65.76c1.25-4.4-2.33-8.76-7.21-8.76H102.93a7.32,7.32,0,0,0-7.4,6l-10,69.61c-.59,4.17,2.89,7.89,7.4,7.89h36.9L115.55,197c-1.12,4.41,2.48,8.55,7.24,8.55a7.58,7.58,0,0,0,6.47-3.48L184,113.85C186.86,109.24,183.29,103.41,177.54,103.41Z"/></g></g></svg>
103+
`

pkg/package-server/storage/subresources_test.go

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,16 @@ import (
1313
"github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/provider"
1414
)
1515

16-
type fakeProvider struct{}
16+
type fakeProvider struct {
17+
packages []*operators.PackageManifest
1718

18-
var getCalls = 0
19+
getCalls int
20+
}
1921

2022
func (p *fakeProvider) Get(namespace, name string) (*operators.PackageManifest, error) {
21-
getCalls = getCalls + 1
23+
p.getCalls = p.getCalls + 1
2224

23-
return &operators.PackageManifest{
24-
Status: operators.PackageManifestStatus{
25-
Channels: []operators.PackageChannel{
26-
{
27-
Name: "stable",
28-
CurrentCSV: "csv-a",
29-
CurrentCSVDesc: operators.CSVDescription{
30-
Icon: []operators.Icon{{Mediatype: "image/png", Base64Data: iconData}},
31-
},
32-
},
33-
},
34-
},
35-
}, nil
25+
return p.packages[0], nil
3626
}
3727

3828
func (p *fakeProvider) List(namespace string) (*operators.PackageManifestList, error) {
@@ -43,6 +33,7 @@ var _ provider.PackageManifestProvider = &fakeProvider{}
4333

4434
func TestLogoStorageConnect(t *testing.T) {
4535
provider := fakeProvider{}
36+
provider.packages = append(provider.packages, testPackage())
4637
ctx, cancel := context.WithCancel(context.TODO())
4738
defer cancel()
4839

@@ -70,11 +61,50 @@ func TestLogoStorageConnect(t *testing.T) {
7061

7162
handler.ServeHTTP(cachedRR, cachedReq)
7263
require.Equal(t, http.StatusNotModified, cachedRR.Code)
73-
require.Equal(t, 1, getCalls, "PackageManifestProvider.Get() should not be called for cached icon")
64+
require.Equal(t, 1, provider.getCalls, "PackageManifestProvider.Get() should not be called for cached icon")
7465

7566
handler.ServeHTTP(rr, req)
7667
require.Equal(t, http.StatusOK, rr.Code)
77-
require.Equal(t, 2, getCalls, "PackageManifestProvider.Get() should be called again to fetch icon")
68+
require.Equal(t, 2, provider.getCalls, "PackageManifestProvider.Get() should be called again to fetch icon")
69+
}
70+
71+
func TestLogoStorageConnectDefaultIcon(t *testing.T) {
72+
provider := fakeProvider{}
73+
provider.packages = append(provider.packages, testPackage())
74+
provider.packages[0].Status.Channels = nil
75+
ctx, cancel := context.WithCancel(context.TODO())
76+
defer cancel()
77+
78+
storage := NewLogoStorage(v1.Resource("packagemanifests/icon"), &provider)
79+
80+
rr := httptest.NewRecorder()
81+
req, err := http.NewRequest("GET", "", nil)
82+
require.NoError(t, err)
83+
84+
handler, err := storage.Connect(ctx, "pkg-a", nil, nil)
85+
require.NoError(t, err)
86+
87+
handler.ServeHTTP(rr, req)
88+
require.Equal(t, http.StatusOK, rr.Code)
89+
require.Equal(t, "image/svg+xml", rr.Header().Get("Content-Type"))
90+
require.NotNil(t, rr.Body)
91+
require.Equal(t, 1, provider.getCalls, "PackageManifestProvider.Get() should be called for missing icon")
92+
}
93+
94+
func testPackage() *operators.PackageManifest {
95+
return &operators.PackageManifest{
96+
Status: operators.PackageManifestStatus{
97+
Channels: []operators.PackageChannel{
98+
{
99+
Name: "stable",
100+
CurrentCSV: "csv-a",
101+
CurrentCSVDesc: operators.CSVDescription{
102+
Icon: []operators.Icon{{Mediatype: "image/png", Base64Data: iconData}},
103+
},
104+
},
105+
},
106+
},
107+
}
78108
}
79109

80110
const iconData = `

0 commit comments

Comments
 (0)