Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): test report storage addition #1271

Open
wants to merge 75 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
a2042f3
ground work
Dec 12, 2024
8fb48dc
feat: add sender rule for pipelines (#1206)
ecrupper Oct 25, 2024
a3b1bff
chore(lint): add struct tag align rule (#1216)
ecrupper Oct 25, 2024
2245376
chore(lint): address existing linter issues (#1218)
ecrupper Nov 4, 2024
5a1f403
enhance(build)!: add fork field for OIDC (#1221)
ecrupper Nov 20, 2024
9a5bf00
enhance(compiler): cache templates per compilation (#1224)
ecrupper Dec 3, 2024
58718a1
ground work
Dec 12, 2024
8e9cd8e
working admin endpoints for bucket management
Dec 17, 2024
3239b53
working admin endpoints for object operations
Dec 18, 2024
8a95775
all endpoints for storage
Jan 2, 2025
a4f29d0
some working test
Jan 7, 2025
41df509
working tests
Jan 8, 2025
86d822d
keys for test report step
Jan 17, 2025
83afd15
feat: deployment config for expected params and targets (#1214)
ecrupper Dec 18, 2024
8b5b79f
resolve conflicts with buildkite
Jan 17, 2025
9328ecd
feat: opt-in gh app integration (#1217)
plyr4 Dec 19, 2024
b16622f
chore(yaml): add go-yaml types package (#1225)
ecrupper Dec 23, 2024
3156794
resolve conflicts
Jan 17, 2025
57f8f9a
rebase
Jan 17, 2025
09da5df
enhance(yaml): allow for users to set version legacy for buildkite (#…
ecrupper Dec 26, 2024
114ae7b
refactor(db/build): drop source index, add event index (#1228)
wass3rw3rk Dec 27, 2024
fd16b7b
feat(repo)!: add pending approval timeout (#1227)
ecrupper Dec 30, 2024
68547d6
enhance(yaml): silent fix anchor merges in YAML maps (#1231)
ecrupper Dec 30, 2024
c7c1d0a
fix(webhook): use correct repo variable for enqueue (#1234)
ecrupper Dec 31, 2024
f43e2d1
feat(pipeline)!: add warnings to pipelines that use legacy YAML lib o…
ecrupper Jan 6, 2025
f1a98ac
feat: status endpoints (#1235)
plyr4 Jan 7, 2025
bf2313d
enhance(deploy): validate on CreateDeployment (#1236)
ecrupper Jan 8, 2025
9a532cf
enhance(metrics): include route specific queue length (#1237)
ecrupper Jan 9, 2025
9f13f97
chore(deps): update codecov/codecov-action action to v5 (#1222)
renovate[bot] Jan 10, 2025
3920eab
fix(deps): update module github.com/google/go-github/v65 to v68 (#1229)
renovate[bot] Jan 10, 2025
084fea3
chore: bump go (#1238)
wass3rw3rk Jan 10, 2025
52df828
fix(deployment): use Config instead of ConfigBackoff when fetching de…
ecrupper Jan 10, 2025
4eee25d
fix(build): use item build host (#1241)
ecrupper Jan 13, 2025
df21b7a
fix(build): ensure count/pagination links account for filter/query pa…
wass3rw3rk Jan 14, 2025
d24fd37
fix(yaml): improved messaging (#1243)
wass3rw3rk Jan 15, 2025
a051afa
keys for test report step
Jan 17, 2025
5254aad
resolve conflicts with buildkite
Jan 17, 2025
a138127
Merge branch 'main' into feat_test_report
timhuynh94 Jan 17, 2025
14660f5
mod tidy
Jan 17, 2025
05a09bb
fields for buildkite and ymal
Jan 20, 2025
657fe54
updates to storage client
Feb 12, 2025
d190aaf
upload with content type and size
Feb 19, 2025
f7942af
working model
Mar 12, 2025
f61dd12
remove test-report types
Mar 12, 2025
446c021
remove test-report.go and build/storage.go
Mar 12, 2025
06a2a52
remove test-report step from compiler validate
Mar 12, 2025
e861dc9
remove test-report step from compiler yaml and buildkite
Mar 12, 2025
05f7df9
white line
Mar 12, 2025
6a8c948
Merge branch 'main' into feat_test_report_storage_addition
timhuynh94 Mar 12, 2025
638c15a
mod tidy
Mar 12, 2025
d87c9d2
fixing upload test
Mar 13, 2025
0825d49
fix setup test
Mar 13, 2025
6a7de50
clean up some endpoints
Mar 17, 2025
c6adfae
Merge branch 'main' into feat_test_report_storage_addition
timhuynh94 Mar 17, 2025
5d12205
rename to client
Mar 17, 2025
6b41dc0
Potential fix for code scanning alert no. 472: Uncontrolled data used…
timhuynh94 Mar 17, 2025
e6ce703
make clean
Mar 17, 2025
203e6b7
gci fix
Mar 17, 2025
7b8bec6
clean up
Mar 17, 2025
73f78a8
mod tidy
Mar 17, 2025
6b6f9fa
gci fix
Mar 17, 2025
b2b717a
typo
Mar 17, 2025
8b0af38
fixing swagger
Mar 17, 2025
8a4997f
remove unused endpoint
Mar 17, 2025
4055774
fix api spec
Mar 17, 2025
d8c3c41
add test for minio
Mar 19, 2025
fdcc0b2
updated test
Mar 21, 2025
135783e
Merge branch 'main' into feat_test_report_storage_addition
timhuynh94 Mar 21, 2025
889d1ff
fix gci and spec
Mar 21, 2025
c80a2bf
fix some test
Mar 25, 2025
73cb815
lint fix
Mar 25, 2025
47d8912
update gci to be what main has
Mar 25, 2025
2da23b6
golint ci fix
Mar 25, 2025
6e07e6c
Merge branch 'main' into feat_test_report_storage_addition
timhuynh94 Mar 25, 2025
feb3400
make clean
Mar 25, 2025
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ release/
*.iml
*.ipr
*.iws
*.xml
#*.xml

# Secrets environment file
secrets.env
Expand Down
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,4 @@ issues:
- funlen
- goconst
- gocyclo
- wsl
- wsl
227 changes: 227 additions & 0 deletions api/admin/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
// SPDX-License-Identifier: Apache-2.0

package admin

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"

"github.com/go-vela/server/api/types"
"github.com/go-vela/server/storage"
"github.com/go-vela/server/util"
)

// swagger:operation POST /api/v1/admin/storage/bucket admin CreateBucket
//
// Create a new bucket
//
// ---
// produces:
// - application/json
// parameters:
// - in: body
// name: body
// description: The bucket name to be created
// required: true
// schema:
// type: object
// properties:
// bucketName:
// type: string
// security:
// - ApiKeyAuth: []
// responses:
// '201':
// description: Successfully created the bucket
// '400':
// description: Invalid request payload
// schema:
// "$ref": "#/definitions/Error"
// '500':
// description: Unexpected server error
// schema:
// "$ref": "#/definitions/Error"

// CreateBucket represents the API handler to create a new bucket.
func CreateBucket(c *gin.Context) {
l := c.MustGet("logger").(*logrus.Entry)
ctx := c.Request.Context()

l.Debug("platform admin: creating bucket")

// capture body from API request
input := new(types.Bucket)

err := c.Bind(input)
if err != nil {
retErr := fmt.Errorf("unable to decode JSON for bucket %s: %w", input.BucketName, err)

util.HandleError(c, http.StatusBadRequest, retErr)

return
}

l.Debugf("bucket name: %s", input.BucketName)

err = storage.FromGinContext(c).CreateBucket(ctx, input)
if err != nil {
retErr := fmt.Errorf("unable to create bucket: %w", err)
util.HandleError(c, http.StatusInternalServerError, retErr)

return
}

c.Status(http.StatusCreated)
}

// swagger:operation GET /api/v1/admin/storage/bucket/download admin DownloadObject
//
// # Download an object from a bucket
//
// ---
// produces:
// - application/json
// parameters:
// - in: query
// name: bucketName
// description: The name of the bucket
// required: true
// type: string
// - in: query
// name: objectName
// description: The name of the object
// required: true
// type: string
// security:
// - ApiKeyAuth: []
// responses:
// '200':
// description: Successfully downloaded the object
// '400':
// description: Invalid request payload
// schema:
// "$ref": "#/definitions/Error"
// '500':
// description: Unexpected server error
// schema:
// "$ref": "#/definitions/Error"

// DownloadObject represents the API handler to download an object from a bucket.
//func DownloadObject(c *gin.Context) {
// l := c.MustGet("logger").(*logrus.Entry)
// ctx := c.Request.Context()
//
// l.Debug("platform admin: downloading object")
//
// // capture body from API request
// input := new(types.Object)
//
// err := c.Bind(input)
// if err != nil {
// retErr := fmt.Errorf("unable to decode JSON for object %s: %w", input.ObjectName, err)
//
// util.HandleError(c, http.StatusBadRequest, retErr)
//
// return
// }
//
// if input.Bucket.BucketName == "" || input.ObjectName == "" {
// retErr := fmt.Errorf("bucketName and objectName are required")
// util.HandleError(c, http.StatusBadRequest, retErr)
//
// return
// }
//
// if input.FilePath == "" {
// retErr := fmt.Errorf("file path is required")
// util.HandleError(c, http.StatusBadRequest, retErr)
//
// return
// }
//
// if strings.ContainsAny(input.FilePath, "/\\") || strings.Contains(input.FilePath, "..") || strings.TrimSpace(input.FilePath) == "" {
// retErr := fmt.Errorf("invalid file path")
// util.HandleError(c, http.StatusBadRequest, retErr)
//
// return
// }
//
// err = storage.FromGinContext(c).Download(ctx, input)
// if err != nil {
// retErr := fmt.Errorf("unable to download object: %w", err)
// util.HandleError(c, http.StatusInternalServerError, retErr)
//
// return
// }
//
// c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("File has been downloaded to %s", input.FilePath)})
//}

// swagger:operation GET /api/v1/admin/storage/presign admin GetPresignedURL
//
// # Generate a presigned URL for an object
//
// ---
// produces:
// - application/json
// parameters:
// - in: query
// name: bucketName
// description: The name of the bucket
// required: true
// type: string
// - in: query
// name: objectName
// description: The name of the object
// required: true
// type: string
// security:
// - ApiKeyAuth: []
// responses:
// '200':
// description: Successfully generated the presigned URL
// '400':
// description: Invalid request payload
// schema:
// "$ref": "#/definitions/Error"
// '500':
// description: Unexpected server error
// schema:
// "$ref": "#/definitions/Error"

// GetPresignedURL represents the API handler to generate a presigned URL for an object.
func GetPresignedURL(c *gin.Context) {
l := c.MustGet("logger").(*logrus.Entry)
ctx := c.Request.Context()

l.Debug("platform admin: generating presigned URL")

// capture query parameters from API request
bucketName := c.Query("bucketName")
objectName := c.Query("objectName")

if bucketName == "" || objectName == "" {
retErr := fmt.Errorf("bucketName and objectName are required")
util.HandleError(c, http.StatusBadRequest, retErr)

return
}

input := &types.Object{
Bucket: types.Bucket{BucketName: bucketName},
ObjectName: objectName,
}

url, err := storage.FromGinContext(c).PresignedGetObject(ctx, input)
if err != nil || url == "" {
retErr := fmt.Errorf("unable to generate presigned URL: %w", err)
util.HandleError(c, http.StatusBadRequest, retErr)

return
}

c.JSON(http.StatusOK, url)
}
8 changes: 8 additions & 0 deletions api/storage/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: Apache-2.0

// Package storage provides the storage handlers for the Vela API.
//
// Usage:
//
// import "github.com/go-vela/server/api/storage"
package storage
115 changes: 115 additions & 0 deletions api/storage/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// SPDX-License-Identifier: Apache-2.0

package storage

import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"

"github.com/go-vela/server/api/types"
"github.com/go-vela/server/storage"
"github.com/go-vela/server/util"
)

// swagger:operation POST /api/v1/storage/info storage StorageInfo
//
// Get storage credentials
//
// ---
// produces:
// - application/json
// security:
// - ApiKeyAuth: []
// responses:
// '200':
// description: Successfully retrieved storage credentials
// schema:
// "$ref": "#/definitions/StorageInfo"
// '401':
// description: Unauthorized
// schema:
// "$ref": "#/definitions/Error"

// Info represents the API handler to
// retrieve storage credentials as part of worker onboarding.
func Info(c *gin.Context) {
l := c.MustGet("logger").(*logrus.Entry)

l.Info("requesting storage credentials with registration token")

// extract the public key that was packed into gin context
k := c.MustGet("access-key").(string)

// extract the storage-address that was packed into gin context
a := c.MustGet("storage-address").(string)

// extract the secret key that was packed into gin context
s := c.MustGet("secret-key").(string)

// extract bucket name that was packed into gin context
b := c.MustGet("storage-bucket").(string)

wr := types.StorageInfo{
StorageAccessKey: &k,
StorageAddress: &a,
StorageSecretKey: &s,
StorageBucket: &b,
}

c.JSON(http.StatusOK, wr)
}

// swagger:operation GET /api/v1/storage/{bucket}/objects storage ListObjects
//
// List objects in a bucket
//
// ---
// produces:
// - application/json
// parameters:
// - in: path
// name: bucket
// description: Name of the bucket
// required: true
// type: string
// security:
// - ApiKeyAuth: []
// responses:
// '200':
// description: Successfully listed objects in the bucket
// schema:
// type: array
// items:
// type: string
// '500':
// description: Unexpected server error
// schema:
// "$ref": "#/definitions/Error"

// ListObjects represents the API handler to list objects in a bucket.
func ListObjects(c *gin.Context) {
l := c.MustGet("logger").(*logrus.Entry)

l.Debug("listing objects in bucket")

// extract the bucket name from the request
bucketName := util.PathParameter(c, "bucket")

// create a new bucket object
b := &types.Bucket{
BucketName: bucketName,
}

// list objects in the bucket
objects, err := storage.FromGinContext(c).ListObjects(c.Request.Context(), b)
if err != nil {
l.Errorf("unable to list objects in bucket %s: %v", bucketName, err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})

return
}

c.JSON(http.StatusOK, gin.H{"objects": objects})
}
22 changes: 22 additions & 0 deletions api/types/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0

package types

import (
"github.com/minio/minio-go/v7"
)

// Bucket is the API types representation of an object storage.
//
// swagger:model CreateBucket
type Bucket struct {
BucketName string `json:"bucket_name,omitempty"`
MakeBucketOptions minio.MakeBucketOptions `json:"make_bucket_options,omitempty"`
ListObjectsOptions minio.ListObjectsOptions `json:"list_objects_options,omitempty"`
}

type Object struct {
ObjectName string `json:"object_name,omitempty"`
Bucket Bucket `json:"bucket,omitempty"`
FilePath string `json:"file_path,omitempty"`
}
Loading
Loading