diff --git a/weed/admin/dash/admin_server.go b/weed/admin/dash/admin_server.go index deb1a9215..550794e6c 100644 --- a/weed/admin/dash/admin_server.go +++ b/weed/admin/dash/admin_server.go @@ -2,7 +2,9 @@ package dash import ( "context" + "errors" "fmt" + "io" "net/http" "sort" "strings" @@ -371,8 +373,21 @@ func (s *AdminServer) GetCredentialManager() *credential.CredentialManager { // InvalidateCache method moved to cluster_topology.go -// GetS3BucketsData retrieves all Object Store buckets and aggregates total storage metrics -func (s *AdminServer) GetS3BucketsData() (S3BucketsData, error) { +// GetS3BucketsData retrieves Object Store buckets with pagination and sorting +func (s *AdminServer) GetS3BucketsData(page, pageSize int, sortBy, sortOrder string) (S3BucketsData, error) { + if page < 1 { + page = 1 + } + if pageSize < 1 || pageSize > 1000 { + pageSize = 100 + } + if sortBy == "" { + sortBy = "name" + } + if sortOrder == "" { + sortOrder = "asc" + } + buckets, err := s.GetS3Buckets() if err != nil { return S3BucketsData{}, err @@ -383,14 +398,97 @@ func (s *AdminServer) GetS3BucketsData() (S3BucketsData, error) { totalSize += bucket.PhysicalSize } + totalBuckets := len(buckets) + + // Sort buckets + s.sortBuckets(buckets, sortBy, sortOrder) + + // Calculate pagination + totalPages := (totalBuckets + pageSize - 1) / pageSize + if totalPages == 0 { + totalPages = 1 + } + if page > totalPages { + page = totalPages + } + + startIndex := (page - 1) * pageSize + endIndex := startIndex + pageSize + if startIndex >= totalBuckets { + buckets = []S3Bucket{} + } else { + if endIndex > totalBuckets { + endIndex = totalBuckets + } + buckets = buckets[startIndex:endIndex] + } + return S3BucketsData{ Buckets: buckets, - TotalBuckets: len(buckets), + TotalBuckets: totalBuckets, TotalSize: totalSize, LastUpdated: time.Now(), + CurrentPage: page, + TotalPages: totalPages, + PageSize: pageSize, + SortBy: sortBy, + SortOrder: sortOrder, }, nil } +// sortBuckets sorts the bucket slice in place by the given field and order +func (s *AdminServer) sortBuckets(buckets []S3Bucket, sortBy, sortOrder string) { + desc := sortOrder == "desc" + sort.Slice(buckets, func(i, j int) bool { + a, b := buckets[i], buckets[j] + switch sortBy { + case "owner": + if a.Owner != b.Owner { + if desc { + return a.Owner > b.Owner + } + return a.Owner < b.Owner + } + case "created": + if !a.CreatedAt.Equal(b.CreatedAt) { + if desc { + return a.CreatedAt.After(b.CreatedAt) + } + return a.CreatedAt.Before(b.CreatedAt) + } + case "objects": + if a.ObjectCount != b.ObjectCount { + if desc { + return a.ObjectCount > b.ObjectCount + } + return a.ObjectCount < b.ObjectCount + } + case "logical_size": + if a.LogicalSize != b.LogicalSize { + if desc { + return a.LogicalSize > b.LogicalSize + } + return a.LogicalSize < b.LogicalSize + } + case "physical_size": + if a.PhysicalSize != b.PhysicalSize { + if desc { + return a.PhysicalSize > b.PhysicalSize + } + return a.PhysicalSize < b.PhysicalSize + } + } + // Tie-breaker: sort by name (also the default/primary for sortBy=="name") + if a.Name != b.Name { + if desc { + return a.Name > b.Name + } + return a.Name < b.Name + } + return false + }) +} + // GetS3Buckets retrieves all Object Store buckets from the filer and collects size/object data from collections func (s *AdminServer) GetS3Buckets() ([]S3Bucket, error) { var buckets []S3Bucket @@ -406,28 +504,48 @@ func (s *AdminServer) GetS3Buckets() ([]S3Bucket, error) { // Now list buckets from the filer and match with collection data err = s.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error { - // List buckets by looking at the buckets directory - stream, err := client.ListEntries(context.Background(), &filer_pb.ListEntriesRequest{ - Directory: filerConfig.BucketsPath, - Prefix: "", - StartFromFileName: "", - InclusiveStartFrom: false, - Limit: 1000, - }) - if err != nil { - return err - } - + // Paginate through all buckets in the buckets directory + const listPageSize = 1000 + startFrom := "" + var snapshotTsNs int64 for { - resp, err := stream.Recv() + stream, err := client.ListEntries(context.Background(), &filer_pb.ListEntriesRequest{ + Directory: filerConfig.BucketsPath, + Prefix: "", + StartFromFileName: startFrom, + InclusiveStartFrom: false, + Limit: listPageSize, + SnapshotTsNs: snapshotTsNs, + }) if err != nil { - if err.Error() == "EOF" { - break - } return err } - if resp.Entry != nil && resp.Entry.IsDirectory { + pageCount := 0 + lastName := "" + for { + resp, err := stream.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + break + } + return err + } + + if snapshotTsNs == 0 && resp.SnapshotTsNs != 0 { + snapshotTsNs = resp.SnapshotTsNs + } + + if resp.Entry == nil { + continue + } + lastName = resp.Entry.Name + pageCount++ + + if !resp.Entry.IsDirectory { + continue + } + bucketName := resp.Entry.Name if strings.HasPrefix(bucketName, ".") { // Skip internal/system directories from Object Store bucket listing. @@ -502,6 +620,12 @@ func (s *AdminServer) GetS3Buckets() ([]S3Bucket, error) { } buckets = append(buckets, bucket) } + + // If we received fewer entries than the page size, we've listed everything + if pageCount < listPageSize { + break + } + startFrom = lastName } return nil diff --git a/weed/admin/dash/bucket_management.go b/weed/admin/dash/bucket_management.go index 4b7d34361..8d83bf818 100644 --- a/weed/admin/dash/bucket_management.go +++ b/weed/admin/dash/bucket_management.go @@ -26,6 +26,15 @@ type S3BucketsData struct { TotalBuckets int `json:"total_buckets"` TotalSize int64 `json:"total_size"` LastUpdated time.Time `json:"last_updated"` + + // Pagination + CurrentPage int `json:"current_page"` + TotalPages int `json:"total_pages"` + PageSize int `json:"page_size"` + + // Sorting + SortBy string `json:"sort_by"` + SortOrder string `json:"sort_order"` } type CreateBucketRequest struct { @@ -48,7 +57,7 @@ type CreateBucketRequest struct { func (s *AdminServer) ShowS3Buckets(w http.ResponseWriter, r *http.Request) { username := UsernameFromContext(r.Context()) - data, err := s.GetS3BucketsData() + data, err := s.GetS3BucketsData(1, 100, "name", "asc") if err != nil { writeJSONError(w, http.StatusInternalServerError, "Failed to get Object Store buckets: "+err.Error()) return diff --git a/weed/admin/handlers/admin_handlers.go b/weed/admin/handlers/admin_handlers.go index 38938c25b..b110c9bff 100644 --- a/weed/admin/handlers/admin_handlers.go +++ b/weed/admin/handlers/admin_handlers.go @@ -3,6 +3,7 @@ package handlers import ( "net/http" "net/url" + "strconv" "time" "github.com/gorilla/mux" @@ -295,8 +296,26 @@ func (h *AdminHandlers) ShowDashboard(w http.ResponseWriter, r *http.Request) { // ShowS3Buckets renders the Object Store buckets management page func (h *AdminHandlers) ShowS3Buckets(w http.ResponseWriter, r *http.Request) { - // Get Object Store buckets data from the server - s3Data := h.getS3BucketsData(r) + // Get pagination and sorting parameters from query string + page := 1 + if p := r.URL.Query().Get("page"); p != "" { + if parsed, err := strconv.Atoi(p); err == nil && parsed > 0 { + page = parsed + } + } + + pageSize := 100 + if ps := r.URL.Query().Get("pageSize"); ps != "" { + if parsed, err := strconv.Atoi(ps); err == nil && parsed > 0 && parsed <= 1000 { + pageSize = parsed + } + } + + sortBy := defaultQuery(r.URL.Query().Get("sortBy"), "name") + sortOrder := defaultQuery(r.URL.Query().Get("sortOrder"), "asc") + + // Get Object Store buckets data with pagination + s3Data := h.getS3BucketsData(r, page, pageSize, sortBy, sortOrder) username := h.getUsername(r) // Render HTML template @@ -463,15 +482,15 @@ func (h *AdminHandlers) ShowBucketDetails(w http.ResponseWriter, r *http.Request writeJSON(w, http.StatusOK, details) } -// getS3BucketsData retrieves Object Store buckets data from the server -func (h *AdminHandlers) getS3BucketsData(r *http.Request) dash.S3BucketsData { +// getS3BucketsData retrieves Object Store buckets data from the server with pagination +func (h *AdminHandlers) getS3BucketsData(r *http.Request, page, pageSize int, sortBy, sortOrder string) dash.S3BucketsData { username := dash.UsernameFromContext(r.Context()) if username == "" { username = "admin" } // Get Object Store buckets data - data, err := h.adminServer.GetS3BucketsData() + data, err := h.adminServer.GetS3BucketsData(page, pageSize, sortBy, sortOrder) if err != nil { // Return empty data on error return dash.S3BucketsData{ @@ -480,6 +499,11 @@ func (h *AdminHandlers) getS3BucketsData(r *http.Request) dash.S3BucketsData { TotalBuckets: 0, TotalSize: 0, LastUpdated: time.Now(), + CurrentPage: 1, + TotalPages: 1, + PageSize: pageSize, + SortBy: sortBy, + SortOrder: sortOrder, } } diff --git a/weed/admin/view/app/s3_buckets.templ b/weed/admin/view/app/s3_buckets.templ index 9f7c138e0..bd7ff71f1 100644 --- a/weed/admin/view/app/s3_buckets.templ +++ b/weed/admin/view/app/s3_buckets.templ @@ -12,12 +12,17 @@ templ S3Buckets(data dash.S3BucketsData) {
- -
@@ -112,12 +117,42 @@ templ S3Buckets(data dash.S3BucketsData) { - - - - - - + + + + + + @@ -256,6 +291,61 @@ templ S3Buckets(data dash.S3BucketsData) {
NameOwnerCreatedObjectsLogical SizePhysical Size + + Name + @getSortIcon("name", data.SortBy, data.SortOrder) + + + + Owner + @getSortIcon("owner", data.SortBy, data.SortOrder) + + + + Created + @getSortIcon("created", data.SortBy, data.SortOrder) + + + + Objects + @getSortIcon("objects", data.SortBy, data.SortOrder) + + + + Logical Size + @getSortIcon("logical_size", data.SortBy, data.SortOrder) + + + + Physical Size + @getSortIcon("physical_size", data.SortBy, data.SortOrder) + + Quota Versioning Object Lock
+ + + if data.TotalPages > 1 { +
+ + Showing { fmt.Sprintf("%d", (data.CurrentPage-1)*data.PageSize+1) } to { fmt.Sprintf("%d", minInt(data.CurrentPage*data.PageSize, data.TotalBuckets)) } of { fmt.Sprintf("%d", data.TotalBuckets) } buckets + + +
+ } @@ -574,6 +664,15 @@ templ S3Buckets(data dash.S3BucketsData) { let cachedUsers = null; document.addEventListener('DOMContentLoaded', function() { + // Add click handlers to pagination links + document.querySelectorAll('.pagination-link').forEach(link => { + link.addEventListener('click', function(e) { + e.preventDefault(); + const page = this.getAttribute('data-page'); + goToPage(page); + }); + }); + // Initialize modal instances once (reuse with show/hide) deleteModalInstance = new bootstrap.Modal(document.getElementById('deleteBucketModal')); quotaModalInstance = new bootstrap.Modal(document.getElementById('manageQuotaModal')); @@ -1032,57 +1131,90 @@ function displayBucketDetails(data) { document.getElementById('bucketDetailsContent').innerHTML = rows.join(''); } + function goToPage(page) { + const url = new URL(window.location); + url.searchParams.set('page', page); + window.location.href = url.toString(); + } + + function changePageSize() { + const pageSize = document.getElementById('pageSizeSelect').value; + const url = new URL(window.location); + url.searchParams.set('pageSize', pageSize); + url.searchParams.set('page', '1'); + window.location.href = url.toString(); + } + + function sortTable(column) { + const url = new URL(window.location); + const currentSort = url.searchParams.get('sortBy'); + const currentOrder = url.searchParams.get('sortOrder') || 'asc'; + + let newOrder = 'asc'; + if (currentSort === column && currentOrder === 'asc') { + newOrder = 'desc'; + } + + url.searchParams.set('sortBy', column); + url.searchParams.set('sortOrder', newOrder); + url.searchParams.set('page', '1'); + window.location.href = url.toString(); + } + function exportBucketList() { // RFC 4180 compliant CSV escaping: escape double quotes by doubling them function escapeCsvField(value) { const str = String(value ?? ''); - // If the field contains comma, double quote, or newline, wrap in quotes and escape internal quotes if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) { return '"' + str.replace(/"/g, '""') + '"'; } return '"' + str + '"'; } - const buckets = Array.from(document.querySelectorAll('#bucketsTable tbody tr')).map(row => { - const cells = row.querySelectorAll('td'); - if (cells.length > 1) { - return { - name: cells[0].textContent.trim(), - owner: cells[1].textContent.trim(), - created: cells[2].textContent.trim(), - objects: cells[3].textContent.trim(), + function formatBytes(bytes) { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + } - logicalSize: cells[4].textContent.trim(), - physicalSize: cells[5].textContent.trim(), - quota: cells[6].textContent.trim(), - versioning: cells[7].textContent.trim(), - objectLock: cells[8].textContent.trim() - }; - } - return null; - }).filter(bucket => bucket !== null); + // Fetch all buckets from the API (not just the current page) + fetch('/api/s3/buckets') + .then(response => response.json()) + .then(data => { + if (data.error) { + alert('Error exporting buckets: ' + data.error); + return; + } - const csvContent = "data:text/csv;charset=utf-8," + - "Name,Owner,Logical Size,Physical Size,Object Count,Created,Quota,Versioning,Object Lock\n" + - buckets.map(b => [ - escapeCsvField(b.name), - escapeCsvField(b.owner), - escapeCsvField(b.logicalSize), - escapeCsvField(b.physicalSize), - escapeCsvField(b.objects), - escapeCsvField(b.created), - escapeCsvField(b.quota), - escapeCsvField(b.versioning), - escapeCsvField(b.objectLock) - ].join(',')).join("\n"); + const buckets = data.buckets || []; + const csvContent = "data:text/csv;charset=utf-8," + + "Name,Owner,Logical Size,Physical Size,Object Count,Created,Quota,Versioning,Object Lock\n" + + buckets.map(b => [ + escapeCsvField(b.name), + escapeCsvField(b.owner), + escapeCsvField(formatBytes(b.logical_size)), + escapeCsvField(formatBytes(b.physical_size)), + escapeCsvField(b.object_count), + escapeCsvField(b.created_at), + escapeCsvField(b.quota_enabled ? formatBytes(b.quota) : 'No quota'), + escapeCsvField(b.versioning_status || 'Not configured'), + escapeCsvField(b.object_lock_enabled ? 'Enabled' : 'Not configured') + ].join(',')).join("\n"); - const encodedUri = encodeURI(csvContent); - const link = document.createElement("a"); - link.setAttribute("href", encodedUri); - link.setAttribute("download", "buckets.csv"); - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); + const encodedUri = encodeURI(csvContent); + const link = document.createElement("a"); + link.setAttribute("href", encodedUri); + link.setAttribute("download", "buckets.csv"); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }) + .catch(error => { + console.error('Error:', error); + alert('Error exporting buckets: ' + error.message); + }); } } diff --git a/weed/admin/view/app/s3_buckets_templ.go b/weed/admin/view/app/s3_buckets_templ.go index 7644bd750..b058d7faa 100644 --- a/weed/admin/view/app/s3_buckets_templ.go +++ b/weed/admin/view/app/s3_buckets_templ.go @@ -34,185 +34,357 @@ func S3Buckets(data dash.S3BucketsData) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

Object Store Buckets

Total Buckets
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

Object Store Buckets

Total Buckets
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalBuckets)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 37, Col: 73} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 42, Col: 73} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
Total Storage
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
Total Storage
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(data.TotalSize)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 57, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 62, Col: 64} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
Last Updated
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
Last Updated
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("15:04:05")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 78, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 83, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
Object Store Buckets
Actions:
Export List
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
Object Store Buckets
Actions:
Export List
NameOwnerCreatedObjectsLogical SizePhysical SizeQuotaVersioningObject LockActions
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, bucket := range data.Buckets { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "\" title=\"Delete Bucket\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(data.Buckets) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "
Name ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.SortBy == "name" { + if data.SortOrder == "asc" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "Owner ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.SortBy == "owner" { + if data.SortOrder == "asc" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "Created ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.SortBy == "created" { + if data.SortOrder == "asc" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "Objects ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.SortBy == "objects" { + if data.SortOrder == "asc" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "Logical Size ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.SortBy == "logical_size" { + if data.SortOrder == "asc" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "Physical Size ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.SortBy == "physical_size" { + if data.SortOrder == "asc" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "QuotaVersioningObject LockActions
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" class=\"text-decoration-none\"> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 134, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 205, Col: 64} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if bucket.Owner != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.Owner) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 140, Col: 101} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 211, Col: 101} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "No owner") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "No owner") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.CreatedAt.Format("2006-01-02 15:04")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 146, Col: 92} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 217, Col: 92} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", bucket.ObjectCount)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 147, Col: 86} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 218, Col: 86} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(bucket.LogicalSize)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 149, Col: 85} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 220, Col: 85} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if bucket.PhysicalSize > 0 && bucket.LogicalSize > 0 && bucket.PhysicalSize > bucket.LogicalSize { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1fx overhead", float64(bucket.PhysicalSize)/float64(bucket.LogicalSize))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 152, Col: 144} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 223, Col: 144} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(bucket.PhysicalSize)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 156, Col: 81} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 227, Col: 81} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if bucket.Quota > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -221,7 +393,7 @@ func S3Buckets(data dash.S3BucketsData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var15 string templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(bucket.Quota)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 161, Col: 86} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 232, Col: 86} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if bucket.QuotaEnabled { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f%% used", float64(bucket.LogicalSize)/float64(bucket.Quota)*100)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 165, Col: 146} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 236, Col: 146} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "
Disabled
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
Disabled
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "No quota") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "No quota") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if bucket.VersioningStatus == "Enabled" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "Enabled") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "Enabled") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if bucket.VersioningStatus == "Suspended" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "Suspended") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "Suspended") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "Not configured") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "Not configured") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if bucket.ObjectLockEnabled { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
Enabled
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "
Enabled
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var17 string templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(bucket.ObjectLockMode) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 195, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 266, Col: 82} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, " • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, " • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d days", bucket.ObjectLockDuration)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 195, Col: 138} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 266, Col: 138} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "Not configured") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "Not configured") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "
No Object Store buckets found

Create your first bucket to get started with S3 storage.

No Object Store buckets found

Create your first bucket to get started with S3 storage.

Last updated: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var27 string - templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05")) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 269, Col: 81} + if data.TotalPages > 1 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "
Showing ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var27 string + templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", (data.CurrentPage-1)*data.PageSize+1)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 335, Col: 101} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, " to ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var28 string + templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", minInt(data.CurrentPage*data.PageSize, data.TotalBuckets))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 335, Col: 185} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, " of ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var29 string + templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", data.TotalBuckets)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 335, Col: 229} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, " buckets
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "
Last updated: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "
Create New S3 Bucket
Bucket names must be between 3 and 63 characters, contain only lowercase letters, numbers, dots, and hyphens.
The S3 identity that owns this bucket. Non-admin users can only access buckets they own.
Set the maximum storage size for this bucket.
Keep multiple versions of objects in this bucket.
Prevent objects from being deleted or overwritten for a specified period. Automatically enables versioning.
Governance allows override with special permissions, Compliance is immutable.
Apply default retention to all new objects in this bucket.
Default retention period for new objects (1-36500 days).
Delete Bucket

Are you sure you want to delete the bucket ?

Warning: This action cannot be undone. All objects in the bucket will be permanently deleted.
Manage Bucket Quota
Set the maximum storage size for this bucket. Set to 0 to remove quota.
Bucket Details
Loading...
Loading bucket details...
Manage Bucket Owner
Select the S3 identity that owns this bucket. Non-admin users can only access buckets they own.
Loading users...
Loading users...
") + var templ_7745c5c3_Var35 string + templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/s3_buckets.templ`, Line: 395, Col: 81} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "
Create New S3 Bucket
Bucket names must be between 3 and 63 characters, contain only lowercase letters, numbers, dots, and hyphens.
The S3 identity that owns this bucket. Non-admin users can only access buckets they own.
Set the maximum storage size for this bucket.
Keep multiple versions of objects in this bucket.
Prevent objects from being deleted or overwritten for a specified period. Automatically enables versioning.
Governance allows override with special permissions, Compliance is immutable.
Apply default retention to all new objects in this bucket.
Default retention period for new objects (1-36500 days).
Delete Bucket

Are you sure you want to delete the bucket ?

Warning: This action cannot be undone. All objects in the bucket will be permanently deleted.
Manage Bucket Quota
Set the maximum storage size for this bucket. Set to 0 to remove quota.
Bucket Details
Loading...
Loading bucket details...
Manage Bucket Owner
Select the S3 identity that owns this bucket. Non-admin users can only access buckets they own.
Loading users...
Loading users...
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }