Skip to content

Commit 82d8a6a

Browse files
authored
feat: configure default cas backend size (#1655)
Signed-off-by: Miguel Martinez <[email protected]>
1 parent f857add commit 82d8a6a

File tree

14 files changed

+326
-176
lines changed

14 files changed

+326
-176
lines changed

app/controlplane/cmd/wire_gen.go

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

app/controlplane/configs/config.devel.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ cas_server:
4343
addr: 0.0.0.0:9001
4444
insecure: true
4545
download_url: http://0.0.0.0:8001/download
46-
46+
default_entry_max_size: 300MB
4747
credentials_service:
4848
vault:
4949
address: ${VAULT_ADDRESS:http://0.0.0.0:8200}

app/controlplane/configs/samples/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ cas_server:
2929
addr: 0.0.0.0:9001
3030
# Where to redirect the user to download artifacts from the CAS
3131
download_url: http://0.0.0.0:8001/download
32+
default_entry_max_size: 1GB
3233

3334
# nats endpoint where to send events
3435
nats_server:

app/controlplane/internal/conf/controlplane/config/v1/conf.pb.go

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

app/controlplane/internal/conf/controlplane/config/v1/conf.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ message Bootstrap {
5858
// In the form of [scheme]://[host]/path i.e https://cas.chainloop.dev/download
5959
// https://github.com/chainloop-dev/chainloop/blob/126f47b6c0803eac844b8e3e1a21d582f00e4dc6/app/artifact-cas/internal/service/download.go#L34
6060
string download_url = 3;
61+
62+
// Default max size for each entry in the CAS backend
63+
// the format is a number followed by a unit, like 100MB, 1GB, etc
64+
// Default is 100MB
65+
string default_entry_max_size = 4;
6166
}
6267

6368
// Configuration for onboarding users in organizations with specific roles

app/controlplane/pkg/biz/casbackend.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"io"
2424
"time"
2525

26+
"code.cloudfoundry.org/bytefmt"
27+
conf "github.com/chainloop-dev/chainloop/app/controlplane/internal/conf/controlplane/config/v1"
2628
backend "github.com/chainloop-dev/chainloop/pkg/blobmanager"
2729
"github.com/chainloop-dev/chainloop/pkg/blobmanager/azureblob"
2830
"github.com/chainloop-dev/chainloop/pkg/blobmanager/oci"
@@ -36,7 +38,6 @@ import (
3638
type CASBackendProvider string
3739

3840
const (
39-
CASBackendDefaultMaxBytes int64 = 100 * 1024 * 1024 // 100MB
4041
// Inline, embedded CAS backend
4142
CASBackendInline CASBackendProvider = "INLINE"
4243
CASBackendInlineDefaultMaxBytes int64 = 500 * 1024 // 500KB
@@ -111,18 +112,28 @@ type CASBackendReader interface {
111112
}
112113

113114
type CASBackendUseCase struct {
114-
repo CASBackendRepo
115-
logger *log.Helper
116-
credsRW credentials.ReaderWriter
117-
providers backend.Providers
115+
repo CASBackendRepo
116+
logger *log.Helper
117+
credsRW credentials.ReaderWriter
118+
providers backend.Providers
119+
MaxBytesDefault int64
118120
}
119121

120-
func NewCASBackendUseCase(repo CASBackendRepo, credsRW credentials.ReaderWriter, providers backend.Providers, l log.Logger) *CASBackendUseCase {
122+
func NewCASBackendUseCase(repo CASBackendRepo, credsRW credentials.ReaderWriter, providers backend.Providers, c *conf.Bootstrap_CASServer, l log.Logger) (*CASBackendUseCase, error) {
121123
if l == nil {
122124
l = log.NewStdLogger(io.Discard)
123125
}
124126

125-
return &CASBackendUseCase{repo, servicelogger.ScopedHelper(l, "biz/CASBackend"), credsRW, providers}
127+
var maxBytesDefault uint64 = 100 * 1024 * 1024 // 100MB
128+
if c.GetDefaultEntryMaxSize() != "" {
129+
var err error
130+
maxBytesDefault, err = bytefmt.ToBytes(c.DefaultEntryMaxSize)
131+
if err != nil {
132+
return nil, fmt.Errorf("invalid CAS backend default max bytes: %w", err)
133+
}
134+
}
135+
136+
return &CASBackendUseCase{repo, servicelogger.ScopedHelper(l, "biz/CASBackend"), credsRW, providers, int64(maxBytesDefault)}, nil
126137
}
127138

128139
func (uc *CASBackendUseCase) List(ctx context.Context, orgID string) ([]*CASBackend, error) {
@@ -253,7 +264,7 @@ func (uc *CASBackendUseCase) Create(ctx context.Context, orgID, name, location,
253264
}
254265

255266
backend, err := uc.repo.Create(ctx, &CASBackendCreateOpts{
256-
MaxBytes: CASBackendDefaultMaxBytes,
267+
MaxBytes: uc.MaxBytesDefault,
257268
Name: name,
258269
CASBackendOpts: &CASBackendOpts{
259270
Location: location, SecretName: secretName, Provider: provider, Default: defaultB,

app/controlplane/pkg/biz/casbackend_test.go

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"errors"
2121
"testing"
2222

23+
conf "github.com/chainloop-dev/chainloop/app/controlplane/internal/conf/controlplane/config/v1"
2324
"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz"
2425
bizMocks "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz/mocks"
2526
backends "github.com/chainloop-dev/chainloop/pkg/blobmanager"
@@ -171,6 +172,99 @@ func (s *casBackendTestSuite) TestPerformValidation() {
171172
})
172173
}
173174

175+
func (s *casBackendTestSuite) TestNewCASBackendUseCase() {
176+
assert := assert.New(s.T())
177+
const defaultErrorMsg = "byte quantity must be a positive integer with a unit of measurement like M, MB, MiB, G, GiB, or GB"
178+
179+
tests := []struct {
180+
name string
181+
config *conf.Bootstrap_CASServer
182+
expectError bool
183+
errorMsg string
184+
wantSize int64 // Expected size in bytes after parsing
185+
}{
186+
{
187+
name: "nil config uses default",
188+
config: nil,
189+
expectError: false,
190+
wantSize: 100 * 1024 * 1024, // 100MB default
191+
},
192+
{
193+
name: "valid size - megabytes",
194+
config: &conf.Bootstrap_CASServer{
195+
DefaultEntryMaxSize: "100MB",
196+
},
197+
expectError: false,
198+
wantSize: 100 * 1024 * 1024,
199+
},
200+
{
201+
name: "valid size - gigabytes",
202+
config: &conf.Bootstrap_CASServer{
203+
DefaultEntryMaxSize: "2GB",
204+
},
205+
expectError: false,
206+
wantSize: 2 * 1024 * 1024 * 1024,
207+
},
208+
{
209+
name: "invalid size format",
210+
config: &conf.Bootstrap_CASServer{
211+
DefaultEntryMaxSize: "invalid",
212+
},
213+
expectError: true,
214+
errorMsg: defaultErrorMsg,
215+
wantSize: 0,
216+
},
217+
{
218+
name: "negative size",
219+
config: &conf.Bootstrap_CASServer{
220+
DefaultEntryMaxSize: "-100MB",
221+
},
222+
expectError: true,
223+
errorMsg: defaultErrorMsg,
224+
wantSize: 0,
225+
},
226+
{
227+
name: "zero size",
228+
config: &conf.Bootstrap_CASServer{
229+
DefaultEntryMaxSize: "0",
230+
},
231+
expectError: true,
232+
errorMsg: defaultErrorMsg,
233+
wantSize: 0,
234+
},
235+
{
236+
name: "missing unit",
237+
config: &conf.Bootstrap_CASServer{
238+
DefaultEntryMaxSize: "100",
239+
},
240+
expectError: true,
241+
errorMsg: defaultErrorMsg,
242+
wantSize: 0,
243+
},
244+
}
245+
246+
for _, tc := range tests {
247+
s.Run(tc.name, func() {
248+
useCase, err := biz.NewCASBackendUseCase(s.repo, s.credsRW,
249+
backends.Providers{
250+
"OCI": s.backendProvider,
251+
}, tc.config, nil)
252+
253+
if tc.expectError {
254+
assert.Error(err)
255+
if tc.errorMsg != "" {
256+
assert.Contains(err.Error(), tc.errorMsg)
257+
}
258+
assert.Nil(useCase)
259+
} else {
260+
assert.NoError(err)
261+
assert.NotNil(useCase)
262+
assert.Equal(tc.wantSize, useCase.MaxBytesDefault)
263+
}
264+
})
265+
}
266+
}
267+
174268
// Run all the tests
175269
func TestCASBackend(t *testing.T) {
176270
suite.Run(t, new(casBackendTestSuite))
@@ -188,9 +282,11 @@ func (s *casBackendTestSuite) SetupTest() {
188282
s.repo = bizMocks.NewCASBackendRepo(s.T())
189283
s.credsRW = credentialsM.NewReaderWriter(s.T())
190284
s.backendProvider = blobM.NewProvider(s.T())
191-
s.useCase = biz.NewCASBackendUseCase(s.repo, s.credsRW,
285+
var err error
286+
s.useCase, err = biz.NewCASBackendUseCase(s.repo, s.credsRW,
192287
backends.Providers{
193288
"OCI": s.backendProvider,
194-
}, nil,
289+
}, nil, nil,
195290
)
291+
s.Require().NoError(err)
196292
}

app/controlplane/pkg/biz/testhelpers/database.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ func NewConfData(db *TestDatabase, t *testing.T) *conf.Data {
201201
}
202202
}
203203

204+
func NewCASBackendConfig() *conf.Bootstrap_CASServer {
205+
return &conf.Bootstrap_CASServer{
206+
DefaultEntryMaxSize: "100MB",
207+
}
208+
}
209+
204210
func NewPromSpec() []*conf.PrometheusIntegrationSpec {
205211
return []*conf.PrometheusIntegrationSpec{}
206212
}

app/controlplane/pkg/biz/testhelpers/wire.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func WireTestData(*TestDatabase, *testing.T, log.Logger, credentials.ReaderWrite
5757
wire.FieldsOf(new(*conf.Data), "Database"),
5858
newNatsConnection,
5959
auditor.NewAuditLogPublisher,
60+
NewCASBackendConfig,
6061
),
6162
)
6263
}

app/controlplane/pkg/biz/testhelpers/wire_gen.go

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

0 commit comments

Comments
 (0)