Skip to content

Commit fc76074

Browse files
authored
feat: default inline CAS backend fallback (#247)
Signed-off-by: Miguel Martinez Trivino <[email protected]>
1 parent 7c5572f commit fc76074

40 files changed

+1183
-238
lines changed

app/cli/cmd/casbackend.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func newCASBackendUpdateCmd() *cobra.Command {
5454
cmd.PersistentFlags().Bool("default", false, "set the backend as default in your organization")
5555
cmd.PersistentFlags().String("description", "", "descriptive information for this registration")
5656

57-
cmd.AddCommand(newCASBackendUpdateOCICmd())
57+
cmd.AddCommand(newCASBackendUpdateOCICmd(), newCASBackendUpdateInlineCmd())
5858
return cmd
5959
}
6060

app/cli/cmd/casbackend_list.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ import (
1919
"fmt"
2020
"time"
2121

22+
"code.cloudfoundry.org/bytefmt"
2223
"github.com/chainloop-dev/chainloop/app/cli/internal/action"
2324
"github.com/jedib0t/go-pretty/v6/table"
25+
"github.com/muesli/reflow/wrap"
2426
"github.com/spf13/cobra"
2527
)
2628

@@ -50,14 +52,19 @@ func casBackendListTableOutput(backends []*action.CASBackendItem) error {
5052
}
5153

5254
t := newTableWriter()
53-
header := table.Row{"ID", "Location", "Provider", "Description", "Default"}
55+
header := table.Row{"ID", "Location", "Provider", "Description", "Limits", "Default"}
5456
if full {
5557
header = append(header, "Validation Status", "Created At", "Validated At")
5658
}
5759

5860
t.AppendHeader(header)
5961
for _, b := range backends {
60-
r := table.Row{b.ID, b.Location, b.Provider, b.Description, b.Default}
62+
limits := "no limits"
63+
if b.Limits != nil {
64+
limits = fmt.Sprintf("MaxSize: %s", bytefmt.ByteSize(uint64(b.Limits.MaxBytes)))
65+
}
66+
67+
r := table.Row{b.ID, wrap.String(b.Location, 35), b.Provider, wrap.String(b.Description, 35), limits, b.Default}
6168
if full {
6269
r = append(r, b.ValidationStatus,
6370
b.CreatedAt.Format(time.RFC822),
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//
2+
// Copyright 2023 The Chainloop Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package cmd
17+
18+
import (
19+
"github.com/chainloop-dev/chainloop/app/cli/internal/action"
20+
"github.com/go-kratos/kratos/v2/log"
21+
"github.com/spf13/cobra"
22+
)
23+
24+
func newCASBackendUpdateInlineCmd() *cobra.Command {
25+
var backendID string
26+
cmd := &cobra.Command{
27+
Use: "inline",
28+
Short: "Update the Inline, fallback CAS Backend description or default status",
29+
RunE: func(cmd *cobra.Command, args []string) error {
30+
isDefault, err := cmd.Flags().GetBool("default")
31+
cobra.CheckErr(err)
32+
33+
description, err := cmd.Flags().GetString("description")
34+
cobra.CheckErr(err)
35+
36+
// If we are overriding the default we ask for confirmation
37+
if isDefault {
38+
if confirmed, err := confirmDefaultCASBackendOverride(actionOpts, backendID); err != nil {
39+
return err
40+
} else if !confirmed {
41+
log.Info("Aborting...")
42+
return nil
43+
}
44+
} else {
45+
// If we are removing the default we ask for confirmation too
46+
if confirmed, err := confirmDefaultCASBackendUnset(backendID, "You are setting the default CAS backend to false", actionOpts); err != nil {
47+
return err
48+
} else if !confirmed {
49+
log.Info("Aborting...")
50+
return nil
51+
}
52+
}
53+
54+
opts := &action.NewCASBackendUpdateOpts{
55+
ID: backendID,
56+
Description: description,
57+
Default: isDefault,
58+
}
59+
60+
res, err := action.NewCASBackendUpdate(actionOpts).Run(opts)
61+
if err != nil {
62+
return err
63+
} else if res == nil {
64+
return nil
65+
}
66+
67+
return encodeOutput([]*action.CASBackendItem{res}, casBackendListTableOutput)
68+
},
69+
}
70+
71+
cmd.Flags().StringVar(&backendID, "id", "", "CAS Backend ID")
72+
err := cmd.MarkFlagRequired("id")
73+
cobra.CheckErr(err)
74+
return cmd
75+
}

app/cli/cmd/config_ocirepository_set.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ func newOCIRepositoryCreateCmd() *cobra.Command {
2424
var repo, username, password string
2525

2626
cmd := &cobra.Command{
27-
Use: "set-oci-repo",
28-
Short: "Set the OCI repository associated with your current org",
27+
Use: "set-oci-repo",
28+
Deprecated: "use 'chainloop cas-backend' instead",
29+
Short: "Set the OCI repository associated with your current org",
2930
RunE: func(cmd *cobra.Command, args []string) error {
3031
opts := &action.NewOCIRepositorySaveOpts{
3132
Repo: repo, Username: username, Password: password,

app/cli/internal/action/attestation_add.go

+23-21
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package action
1818
import (
1919
"context"
2020
"errors"
21+
"fmt"
2122

2223
pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1"
2324
"github.com/chainloop-dev/chainloop/internal/attestation/crafter"
@@ -63,7 +64,7 @@ func (action *AttestationAdd) Run(k, v string) error {
6364
return err
6465
}
6566

66-
// Get upload creds for the current attestation and set up CAS client
67+
// Get upload creds and CASbackend for the current attestation and set up CAS client
6768
client := pb.NewAttestationServiceClient(action.CPConnection)
6869
creds, err := client.GetUploadCreds(context.Background(),
6970
&pb.AttestationServiceGetUploadCredsRequest{
@@ -73,31 +74,32 @@ func (action *AttestationAdd) Run(k, v string) error {
7374
if err != nil {
7475
return err
7576
}
76-
artifactCASConn, err := grpcconn.New(action.casURI, creds.Result.Token, action.connectionInsecure)
77-
if err != nil {
78-
return err
79-
}
80-
defer artifactCASConn.Close()
8177

82-
cc := casclient.New(artifactCASConn, casclient.WithLogger(action.Logger))
78+
b := creds.GetResult().GetBackend()
79+
if b == nil {
80+
return fmt.Errorf("no backend found in upload creds")
81+
}
8382

84-
// // TODO: retrieve this information from backend
85-
backend := &casclient.CASBackend{
86-
Uploader: cc,
87-
Name: "OCI",
88-
// 100MB max size
89-
MaxSize: 100 * 1024 * 1024,
83+
// Define CASbackend information based on the API response
84+
casBackend := &casclient.CASBackend{
85+
Name: b.Provider,
86+
MaxSize: b.GetLimits().MaxBytes,
9087
}
9188

92-
// backend := &casclient.CASBackend{
93-
// Name: "INLINE",
94-
// // 500KB max size
95-
// MaxSize: 500 * 1024,
96-
// }
89+
// Some CASBackends will actually upload information to the CAS server
90+
// in such case we need to set up a connection
91+
if !b.IsInline && creds.Result.Token != "" {
92+
artifactCASConn, err := grpcconn.New(action.casURI, creds.Result.Token, action.connectionInsecure)
93+
if err != nil {
94+
return err
95+
}
96+
defer artifactCASConn.Close()
9797

98-
if err := action.c.AddMaterial(k, v, backend); err != nil {
99-
action.Logger.Err(err).Msg("adding material")
100-
return err
98+
casBackend.Uploader = casclient.New(artifactCASConn, casclient.WithLogger(action.Logger))
99+
}
100+
101+
if err := action.c.AddMaterial(k, v, casBackend); err != nil {
102+
return fmt.Errorf("adding material: %w", err)
101103
}
102104

103105
return nil

app/cli/internal/action/casbackend_list.go

+20-6
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,24 @@ type CASBackendList struct {
2727
}
2828

2929
type CASBackendItem struct {
30-
ID string `json:"id"`
31-
Location string `json:"location"`
32-
Description string `json:"description"`
33-
Provider string `json:"provider"`
34-
Default bool `json:"default"`
35-
ValidationStatus ValidationStatus `json:"validationStatus"`
30+
ID string `json:"id"`
31+
Location string `json:"location"`
32+
Description string `json:"description"`
33+
Provider string `json:"provider"`
34+
Default bool `json:"default"`
35+
Inline bool `json:"inline"`
36+
Limits *CASBackendLimits `json:"limits"`
37+
ValidationStatus ValidationStatus `json:"validationStatus"`
3638

3739
CreatedAt *time.Time `json:"createdAt"`
3840
ValidatedAt *time.Time `json:"validatedAt"`
3941
}
4042

43+
type CASBackendLimits struct {
44+
// Max number of bytes allowed to be stored in this backend
45+
MaxBytes int64
46+
}
47+
4148
type ValidationStatus string
4249

4350
const (
@@ -77,6 +84,13 @@ func pbCASBackendItemToAction(in *pb.CASBackendItem) *CASBackendItem {
7784
Default: in.Default,
7885
CreatedAt: toTimePtr(in.CreatedAt.AsTime()),
7986
ValidatedAt: toTimePtr(in.ValidatedAt.AsTime()),
87+
Inline: in.IsInline,
88+
}
89+
90+
if in.Limits != nil {
91+
b.Limits = &CASBackendLimits{
92+
MaxBytes: in.Limits.MaxBytes,
93+
}
8094
}
8195

8296
switch in.GetValidationStatus() {

app/cli/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ func errorInfo(err error, logger zerolog.Logger) (string, int) {
5555
// Make overrides
5656
switch {
5757
case v1.IsOciRepositoryErrorReasonRequired(err):
58-
msg = "you need to set up an OCI repository first. Refer to https://docs.chainloop.dev/getting-started/setup#add-oci-repository for more information."
58+
msg = "you need to enable a CAS backend first. Refer to `chainloop cas-backend` command or contact your administrator."
5959
case v1.IsOciRepositoryErrorReasonInvalid(err):
60-
msg = "the OCI repository you provided is invalid. Refer to https://docs.chainloop.dev/getting-started/setup#add-oci-repository for more information."
60+
msg = "the CAS backend you provided is invalid. Refer to `chainloop cas-backend update` command or contact your administrator."
6161
case v1.IsAllowListErrorNotInList(err):
6262
msg = "your user is not part of the private beta yet. You can request access at https://docs.chainloop.dev/getting-started/private-beta"
6363
case isWrappedErr(st, jwtMiddleware.ErrTokenExpired):

app/controlplane/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ migration_apply: check-atlas-tool migration_hash
3434

3535
.PHONY: migration_new
3636
# generate new migration if needed from the current ent schema
37-
migration_new: check-atlas-tool
37+
migration_new: check-atlas-tool migration_hash
3838
atlas migrate diff --dir ${local_migrations_dir} --to "ent://internal/data/ent/schema" --dev-url "docker://postgres/15/test?search_path=public"
3939

4040
.PHONY: migration_hash
@@ -60,7 +60,7 @@ lint: check-golangci-lint-tool check-buf-tool
6060

6161
.PHONY: generate
6262
# generate proto bindings, wire injectors, and ent models
63-
generate: check-wire-tool api config
63+
generate: check-wire-tool api config migration_new
6464
go generate ./...
6565

6666
.PHONY: all

0 commit comments

Comments
 (0)