Skip to content

Commit 9254a2e

Browse files
camilamacedo86perdasilva
authored andcommitted
fix: bundle size validator: ammount compressed scenarios should be lower than < ~1MB and add improvement to show uncompressed ammount
Upstream-repository: api Upstream-commit: 02354fceffa1bc8a6e8e471d4f123352d330daa9
1 parent 0eb506a commit 9254a2e

File tree

7 files changed

+157
-54
lines changed

7 files changed

+157
-54
lines changed

staging/api/pkg/manifests/bundle.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ type Bundle struct {
2020
V1CRDs []*apiextensionsv1.CustomResourceDefinition
2121
Dependencies []*Dependency
2222
// CompressedSize stores the gzip size of the bundle
23-
CompressedSize *int64
23+
CompressedSize int64
24+
// Size stores the size of the bundle
25+
Size int64
2426
}
2527

2628
func (b *Bundle) ObjectsToValidate() []interface{} {

staging/api/pkg/manifests/bundleloader.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,30 @@ func (b *bundleLoader) LoadBundle() error {
4949

5050
// Compress the bundle to check its size
5151
func (b *bundleLoader) calculateCompressedBundleSize() error {
52+
if b.bundle == nil {
53+
return nil
54+
}
5255
err := filepath.Walk(b.dir,
5356
func(path string, info os.FileInfo, err error) error {
5457
if err != nil {
5558
return err
5659
}
60+
if info.IsDir() {
61+
return nil
62+
}
63+
data, err := os.ReadFile(path)
64+
if err == nil {
65+
// Sum the bundle amount
66+
b.bundle.Size += info.Size()
5767

58-
if !info.IsDir() {
59-
if data, err := os.ReadFile(path); err == nil {
60-
content, err := encoding.GzipBase64Encode(data)
61-
if err != nil {
62-
return err
63-
}
64-
total := int64(len(content))
65-
if b.bundle.CompressedSize != nil {
66-
total += *b.bundle.CompressedSize
67-
}
68-
b.bundle.CompressedSize = &total
68+
// Sum the compressed amount
69+
contentGzip, err := encoding.GzipBase64Encode(data)
70+
if err != nil {
71+
return err
6972
}
73+
b.bundle.CompressedSize += int64(len(contentGzip))
7074
}
71-
return nil
75+
return err
7276
})
7377
if err != nil {
7478
return err

staging/api/pkg/validation/internal/bundle.go

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ var BundleValidator interfaces.Validator = interfaces.ValidatorFunc(validateBund
1717

1818
// max_bundle_size is the maximum size of a bundle in bytes.
1919
// This ensures the bundle can be staged in a single ConfigMap by OLM during installation.
20-
// The value is derived from the standard upper bound for k8s resources (~4MB).
21-
const max_bundle_size = 4 << (10 * 2)
20+
// The value is derived from the standard upper bound for k8s resources (~1MB).
21+
// We will use this value to check the bundle compressed is < ~1MB
22+
const max_bundle_size = int64(1 << (10 * 2))
2223

2324
func validateBundles(objs ...interface{}) (results []errors.ManifestResult) {
2425
for _, obj := range objs {
@@ -133,23 +134,55 @@ func getOwnedCustomResourceDefintionKeys(csv *operatorsv1alpha1.ClusterServiceVe
133134
// - we could identify that the bundle size is close to the limit (bigger than 85%)
134135
func validateBundleSize(bundle *manifests.Bundle) []errors.Error {
135136
warnPercent := 0.85
136-
warnSize := int64(max_bundle_size * warnPercent)
137+
warnSize := float64(max_bundle_size) * warnPercent
137138
var errs []errors.Error
138139

139-
if bundle.CompressedSize == nil || *bundle.CompressedSize == 0 {
140-
errs = append(errs, errors.WarnFailedValidation("unable to check the bundle size", nil))
140+
if bundle.CompressedSize == 0 {
141+
errs = append(errs, errors.WarnFailedValidation("unable to check the bundle compressed size", bundle.Name))
141142
return errs
142143
}
143144

144-
if *bundle.CompressedSize > max_bundle_size {
145-
errs = append(errs, errors.ErrInvalidBundle(fmt.Sprintf("maximum bundle compressed size with gzip size exceeded: size=~%d MegaByte, max=%d MegaByte", *bundle.CompressedSize/(1<<(10*2)), max_bundle_size/(1<<(10*2))), nil))
146-
} else if *bundle.CompressedSize > warnSize {
147-
errs = append(errs, errors.WarnInvalidBundle(fmt.Sprintf("nearing maximum bundle compressed size with gzip: size=~%d MegaByte, max=%d MegaByte", *bundle.CompressedSize/(1<<(10*2)), max_bundle_size/(1<<(10*2))), nil))
145+
if bundle.Size == 0 {
146+
errs = append(errs, errors.WarnFailedValidation("unable to check the bundle size", bundle.Name))
147+
return errs
148+
}
149+
150+
// From OPM (https://github.com/operator-framework/operator-registry) 1.17.5
151+
// and OLM (https://github.com/operator-framework/operator-lifecycle-manager) : v0.19.0
152+
// the total size checked is compressed
153+
if bundle.CompressedSize > max_bundle_size {
154+
errs = append(errs, errors.ErrInvalidBundle(
155+
fmt.Sprintf("maximum bundle compressed size with gzip size exceeded: size=~%s , max=%s. Bundle uncompressed size is %s",
156+
formatBytesInUnit(bundle.CompressedSize),
157+
formatBytesInUnit(max_bundle_size),
158+
formatBytesInUnit(bundle.Size)),
159+
bundle.Name))
160+
} else if float64(bundle.CompressedSize) > warnSize {
161+
errs = append(errs, errors.WarnInvalidBundle(
162+
fmt.Sprintf("nearing maximum bundle compressed size with gzip: size=~%s , max=%s. Bundle uncompressed size is %s",
163+
formatBytesInUnit(bundle.CompressedSize),
164+
formatBytesInUnit(max_bundle_size),
165+
formatBytesInUnit(bundle.Size)),
166+
bundle.Name))
148167
}
149168

150169
return errs
151170
}
152171

172+
func formatBytesInUnit(b int64) string {
173+
const unit = 1000
174+
if b < unit {
175+
return fmt.Sprintf("%d B", b)
176+
}
177+
div, exp := int64(unit), 0
178+
for n := b / unit; n >= unit; n /= unit {
179+
div *= unit
180+
exp++
181+
}
182+
return fmt.Sprintf("%.1f %cB",
183+
float64(b)/float64(div), "kMGTPE"[exp])
184+
}
185+
153186
// getBundleCRDKeys returns a set of definition keys for all CRDs in bundle.
154187
func getBundleCRDKeys(bundle *manifests.Bundle) (keys []schema.GroupVersionKind) {
155188
// Collect all v1 and v1beta1 CRD keys, skipping group which CSVs do not support.

staging/api/pkg/validation/internal/bundle_test.go

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package internal
22

33
import (
4+
"fmt"
45
"testing"
56

67
"github.com/stretchr/testify/require"
@@ -164,7 +165,8 @@ func TestValidateServiceAccount(t *testing.T) {
164165

165166
func TestBundleSize(t *testing.T) {
166167
type args struct {
167-
size int64
168+
sizeCompressed int64
169+
size int64
168170
}
169171
tests := []struct {
170172
name string
@@ -177,35 +179,54 @@ func TestBundleSize(t *testing.T) {
177179
{
178180
name: "should pass when the size is not bigger or closer of the limit",
179181
args: args{
180-
size: int64(max_bundle_size / 2),
182+
sizeCompressed: max_bundle_size / 2,
183+
size: max_bundle_size / 2,
181184
},
182185
},
183186
{
184187
name: "should warn when the size is closer of the limit",
185188
args: args{
186-
size: int64(max_bundle_size - 10),
189+
sizeCompressed: max_bundle_size - 100000,
190+
size: (max_bundle_size - 100000) * 10,
187191
},
188192
wantWarning: true,
189-
warnStrings: []string{"Warning: : nearing maximum bundle compressed size with gzip: size=~3 MegaByte, max=4 MegaByte"},
193+
warnStrings: []string{
194+
"Warning: Value : nearing maximum bundle compressed size with gzip: size=~948.6 kB , max=1.0 MB. Bundle uncompressed size is 9.5 MB",
195+
},
196+
},
197+
{
198+
name: "should warn when is not possible to check the size compressed",
199+
args: args{
200+
size: max_bundle_size * 1024,
201+
},
202+
wantWarning: true,
203+
warnStrings: []string{"Warning: Value : unable to check the bundle compressed size"},
190204
},
191205
{
192-
name: "should warn when is not possible to check the size",
206+
name: "should warn when is not possible to check the size",
207+
args: args{
208+
sizeCompressed: max_bundle_size / 2,
209+
},
193210
wantWarning: true,
194-
warnStrings: []string{"Warning: : unable to check the bundle size"},
211+
warnStrings: []string{"Warning: Value : unable to check the bundle size"},
195212
},
196213
{
197214
name: "should raise an error when the size is bigger than the limit",
198215
args: args{
199-
size: int64(2 * max_bundle_size),
216+
sizeCompressed: 2 * max_bundle_size,
217+
size: (2 * max_bundle_size) * 10,
218+
},
219+
wantError: true,
220+
errStrings: []string{
221+
"Error: Value : maximum bundle compressed size with gzip size exceeded: size=~2.1 MB , max=1.0 MB. Bundle uncompressed size is 21.0 MB",
200222
},
201-
wantError: true,
202-
errStrings: []string{"Error: : maximum bundle compressed size with gzip size exceeded: size=~8 MegaByte, max=4 MegaByte"},
203223
},
204224
}
205225
for _, tt := range tests {
206226
t.Run(tt.name, func(t *testing.T) {
207227
bundle := &manifests.Bundle{
208-
CompressedSize: &tt.args.size,
228+
CompressedSize: tt.args.sizeCompressed,
229+
Size: tt.args.size,
209230
}
210231
result := validateBundleSize(bundle)
211232

@@ -265,6 +286,10 @@ func Test_EnsureGetBundleSizeValue(t *testing.T) {
265286
bundle, err := manifests.GetBundleFromDir(tt.args.bundleDir)
266287
require.NoError(t, err)
267288

289+
// Should have the values calculated
290+
require.Greater(t, bundle.Size, int64(0), fmt.Sprintf("the bundle size is %d when should be > 0", bundle.Size))
291+
require.Greater(t, bundle.CompressedSize, int64(0), fmt.Sprintf("the bundle compressed size is %d when should be > 0", bundle.CompressedSize))
292+
268293
results := validateBundle(bundle)
269294
require.Equal(t, tt.wantWarning, len(results.Warnings) > 0)
270295
if tt.wantWarning {

vendor/github.com/operator-framework/api/pkg/manifests/bundle.go

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/operator-framework/api/pkg/manifests/bundleloader.go

Lines changed: 16 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/operator-framework/api/pkg/validation/internal/bundle.go

Lines changed: 42 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)