Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions internal/command/extensions/tigris/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ func create() (cmd *cobra.Command) {
}

func runCreate(ctx context.Context) (err error) {
bucketName := flag.GetString(ctx, "name")
if err := validateBucketName(bucketName); err != nil {
return err
}

appName := appconfig.NameFromContext(ctx)
params := extensions_core.ExtensionParams{}

Expand Down Expand Up @@ -121,3 +126,24 @@ func isShadowBucketSpecified(accessKey, secretKey, region, name, endpoint string
}
return n == len(values), nil
}

// validateBucketName validates that the bucket name length is within the allowed range.
// Bucket names must be between 3 and 63 characters.
// See: https://www.tigrisdata.com/docs/buckets/bucket-rules/
func validateBucketName(name string) error {
const bucketNamingRulesURL = "https://www.tigrisdata.com/docs/buckets/bucket-rules/"

if name == "" {
return nil // Empty name will be handled by the prompt or auto-generated
}

if len(name) < 3 {
return fmt.Errorf("bucket name %q is too short: must be at least 3 characters, got %d. See %s", name, len(name), bucketNamingRulesURL)
}

if len(name) > 63 {
return fmt.Errorf("bucket name %q is too long: must be at most 63 characters, got %d. See %s", name, len(name), bucketNamingRulesURL)
}

return nil
}
75 changes: 75 additions & 0 deletions internal/command/extensions/tigris/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package tigris

import (
"strings"
"testing"
)

func TestValidateBucketName(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
errSubstr string
}{
{
name: "empty name is valid (will be prompted or auto-generated)",
input: "",
wantErr: false,
},
{
name: "too short - 1 character",
input: "a",
wantErr: true,
errSubstr: "too short",
},
{
name: "too short - 2 characters",
input: "ab",
wantErr: true,
errSubstr: "too short",
},
{
name: "valid - minimum 3 characters",
input: "abc",
wantErr: false,
},
{
name: "valid - typical bucket name",
input: "my-bucket-123",
wantErr: false,
},
{
name: "valid - maximum 63 characters",
input: "a23456789012345678901234567890123456789012345678901234567890123",
wantErr: false,
},
{
name: "too long - 64 characters (user's original issue)",
input: "nexus-staging-chore-new-mechanism-to-translate-city-names-assets",
wantErr: true,
errSubstr: "too long",
},
{
name: "too long - 100 characters",
input: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
wantErr: true,
errSubstr: "too long",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validateBucketName(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("validateBucketName(%q) error = %v, wantErr %v", tt.input, err, tt.wantErr)
return
}
if tt.wantErr && tt.errSubstr != "" {
if err == nil || !strings.Contains(err.Error(), tt.errSubstr) {
t.Errorf("validateBucketName(%q) error = %v, want error containing %q", tt.input, err, tt.errSubstr)
}
}
})
}
}