From a2042f318f47ae8ee951018a4bb9392749498006 Mon Sep 17 00:00:00 2001 From: TimHuynh Date: Thu, 12 Dec 2024 09:41:14 -0600 Subject: [PATCH] ground work --- api/types/test-report/code_coverage_file.go | 214 +++++++ api/types/test-report/code_coverage_group.go | 99 ++++ api/types/test-report/code_coverage_run.go | 57 ++ api/types/test-report/code_coverage_stats.go | 214 +++++++ api/types/test-report/performance_results.go | 130 +++++ api/types/test-report/results_metadata.go | 115 ++++ api/types/test-report/results_processing.go | 118 ++++ .../test-report/results_processing_failure.go | 169 ++++++ api/types/test-report/shedlock.go | 115 ++++ api/types/test-report/test_case.go | 419 +++++++++++++ api/types/test-report/test_failure.go | 132 +++++ api/types/test-report/test_run.go | 319 ++++++++++ api/types/test-report/test_run_attachment.go | 11 + .../test-report/test_run_system_attributes.go | 47 ++ api/types/test-report/test_suite.go | 552 ++++++++++++++++++ api/types/test-report/test_suite_group.go | 142 +++++ cmd/vela-server/main.go | 4 + cmd/vela-server/server.go | 6 + constants/driver.go | 8 + docker-compose.yml | 10 + go.mod | 33 +- go.sum | 67 ++- storage/context.go | 59 ++ storage/context_test.go | 118 ++++ storage/flags.go | 49 ++ storage/minio/bucket_exists.go | 16 + storage/minio/create_bucket.go | 25 + storage/minio/delete_bucket.go | 14 + storage/minio/doc.go | 1 + storage/minio/download.go | 16 + storage/minio/get_bucket_lifecycle.go | 20 + storage/minio/list_bucket.go | 21 + storage/minio/list_objects.go | 23 + storage/minio/minio.go | 115 ++++ storage/minio/opts.go | 54 ++ storage/minio/set_bucket_lifecycle.go | 20 + storage/minio/upload.go | 16 + storage/service.go | 28 + storage/setup.go | 73 +++ storage/storage.go | 55 ++ 40 files changed, 3689 insertions(+), 15 deletions(-) create mode 100644 api/types/test-report/code_coverage_file.go create mode 100644 api/types/test-report/code_coverage_group.go create mode 100644 api/types/test-report/code_coverage_run.go create mode 100644 api/types/test-report/code_coverage_stats.go create mode 100644 api/types/test-report/performance_results.go create mode 100644 api/types/test-report/results_metadata.go create mode 100644 api/types/test-report/results_processing.go create mode 100644 api/types/test-report/results_processing_failure.go create mode 100644 api/types/test-report/shedlock.go create mode 100644 api/types/test-report/test_case.go create mode 100644 api/types/test-report/test_failure.go create mode 100644 api/types/test-report/test_run.go create mode 100644 api/types/test-report/test_run_attachment.go create mode 100644 api/types/test-report/test_run_system_attributes.go create mode 100644 api/types/test-report/test_suite.go create mode 100644 api/types/test-report/test_suite_group.go create mode 100644 storage/context.go create mode 100644 storage/context_test.go create mode 100644 storage/flags.go create mode 100644 storage/minio/bucket_exists.go create mode 100644 storage/minio/create_bucket.go create mode 100644 storage/minio/delete_bucket.go create mode 100644 storage/minio/doc.go create mode 100644 storage/minio/download.go create mode 100644 storage/minio/get_bucket_lifecycle.go create mode 100644 storage/minio/list_bucket.go create mode 100644 storage/minio/list_objects.go create mode 100644 storage/minio/minio.go create mode 100644 storage/minio/opts.go create mode 100644 storage/minio/set_bucket_lifecycle.go create mode 100644 storage/minio/upload.go create mode 100644 storage/service.go create mode 100644 storage/setup.go create mode 100644 storage/storage.go diff --git a/api/types/test-report/code_coverage_file.go b/api/types/test-report/code_coverage_file.go new file mode 100644 index 000000000..31b513b93 --- /dev/null +++ b/api/types/test-report/code_coverage_file.go @@ -0,0 +1,214 @@ +package test_report + +// CodeCoverageFile is the API types representation of a code coverage file for a pipeline. +// +// swagger:model CodeCoverageFile +type CodeCoverageFile struct { + ID *int64 `json:"id,omitempty"` + CodeCoverageRun *CodeCoverageRun `json:"code_coverage_run,omitempty"` + CodeCoverageGroup *CodeCoverageGroup `json:"code_coverage_group,omitempty"` + CodeCoverageStats *CodeCoverageStats `json:"code_coverage_stats,omitempty"` + DirectoryName *string `json:"directory_name,omitempty"` + FileName *string `json:"file_name,omitempty"` + MissedLines *int `json:"missed_lines,omitempty"` + PartialLines *int `json:"partial_lines,omitempty"` + FilePath *string `json:"file_path,omitempty"` +} + +// GetID returns the ID field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// SetID sets the ID field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetID(v int64) { + if c == nil { + return + } + c.ID = &v +} + +// GetCodeCoverageRun returns the CodeCoverageRun field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetCodeCoverageRun() *CodeCoverageRun { + if c == nil || c.CodeCoverageRun == nil { + return new(CodeCoverageRun) + } + return c.CodeCoverageRun +} + +// SetCodeCoverageRun sets the CodeCoverageRun field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetCodeCoverageRun(v *CodeCoverageRun) { + if c == nil { + return + } + c.CodeCoverageRun = v +} + +// GetCodeCoverageGroup returns the CodeCoverageGroup field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetCodeCoverageGroup() *CodeCoverageGroup { + if c == nil || c.CodeCoverageGroup == nil { + return new(CodeCoverageGroup) + } + return c.CodeCoverageGroup +} + +// SetCodeCoverageGroup sets the CodeCoverageGroup field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetCodeCoverageGroup(v *CodeCoverageGroup) { + if c == nil { + return + } + c.CodeCoverageGroup = v +} + +// GetCodeCoverageStats returns the CodeCoverageStats field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetCodeCoverageStats() *CodeCoverageStats { + if c == nil || c.CodeCoverageStats == nil { + return new(CodeCoverageStats) + } + return c.CodeCoverageStats +} + +// SetCodeCoverageStats sets the CodeCoverageStats field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetCodeCoverageStats(v *CodeCoverageStats) { + if c == nil { + return + } + c.CodeCoverageStats = v +} + +// GetDirectoryName returns the DirectoryName field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetDirectoryName() string { + if c == nil || c.DirectoryName == nil { + return "" + } + return *c.DirectoryName +} + +// SetDirectoryName sets the DirectoryName field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetDirectoryName(v string) { + if c == nil { + return + } + c.DirectoryName = &v +} + +// GetFileName returns the FileName field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetFileName() string { + if c == nil || c.FileName == nil { + return "" + } + return *c.FileName +} + +// SetFileName sets the FileName field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetFileName(v string) { + if c == nil { + return + } + c.FileName = &v +} + +// GetMissedLines returns the MissedLines field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetMissedLines() int { + if c == nil || c.MissedLines == nil { + return 0 + } + return *c.MissedLines +} + +// SetMissedLines sets the MissedLines field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetMissedLines(v int) { + if c == nil { + return + } + c.MissedLines = &v +} + +// GetPartialLines returns the PartialLines field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetPartialLines() int { + if c == nil || c.PartialLines == nil { + return 0 + } + return *c.PartialLines +} + +// SetPartialLines sets the PartialLines field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetPartialLines(v int) { + if c == nil { + return + } + c.PartialLines = &v +} + +// GetFilePath returns the FilePath field. +// +// When the provided CodeCoverageFile type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageFile) GetFilePath() string { + if c == nil || c.FilePath == nil { + return "" + } + return *c.FilePath +} + +// SetFilePath sets the FilePath field. +// +// When the provided CodeCoverageFile type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageFile) SetFilePath(v string) { + if c == nil { + return + } + c.FilePath = &v +} diff --git a/api/types/test-report/code_coverage_group.go b/api/types/test-report/code_coverage_group.go new file mode 100644 index 000000000..88e832701 --- /dev/null +++ b/api/types/test-report/code_coverage_group.go @@ -0,0 +1,99 @@ +package test_report + +// CodeCoverageGroup is the API types representation of a group of code coverage. +// +// swagger:model CodeCoverageGroup +type CodeCoverageGroup struct { + ID *int64 `json:"id,omitempty"` + CodeCoverageRun *CodeCoverageRun `json:"code_coverage_run,omitempty"` + Name *string `json:"name,omitempty"` + CodeCoverageStats *CodeCoverageStats `json:"code_coverage_stats,omitempty"` +} + +// GetID returns the ID field. +// +// When the provided CodeCoverageGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageGroup) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// SetID sets the ID field. +// +// When the provided CodeCoverageGroup type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageGroup) SetID(v int64) { + if c == nil { + return + } + c.ID = &v +} + +// GetCodeCoverageRun returns the CodeCoverageRun field. +// +// When the provided CodeCoverageGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageGroup) GetCodeCoverageRun() *CodeCoverageRun { + if c == nil || c.CodeCoverageRun == nil { + return new(CodeCoverageRun) + } + return c.CodeCoverageRun +} + +// SetCodeCoverageRun sets the CodeCoverageRun field. +// +// When the provided CodeCoverageGroup type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageGroup) SetCodeCoverageRun(v *CodeCoverageRun) { + if c == nil { + return + } + c.CodeCoverageRun = v +} + +// GetName returns the Name field. +// +// When the provided CodeCoverageGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageGroup) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// SetName sets the Name field. +// +// When the provided CodeCoverageGroup type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageGroup) SetName(v string) { + if c == nil { + return + } + c.Name = &v +} + +// GetCodeCoverageStats returns the CodeCoverageStats field. +// +// When the provided CodeCoverageGroup type is nil, or the field within +// the type is nil, it returns a new CodeCoverageStats instance. +func (c *CodeCoverageGroup) GetCodeCoverageStats() *CodeCoverageStats { + if c == nil || c.CodeCoverageStats == nil { + return new(CodeCoverageStats) + } + return c.CodeCoverageStats +} + +// SetCodeCoverageStats sets the CodeCoverageStats field. +// +// When the provided CodeCoverageGroup type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageGroup) SetCodeCoverageStats(v *CodeCoverageStats) { + if c == nil { + return + } + c.CodeCoverageStats = v +} diff --git a/api/types/test-report/code_coverage_run.go b/api/types/test-report/code_coverage_run.go new file mode 100644 index 000000000..23128be83 --- /dev/null +++ b/api/types/test-report/code_coverage_run.go @@ -0,0 +1,57 @@ +package test_report + +// CodeCoverageRun is the API types representation of a code coverage run for a pipeline. +// +// swagger:model CodeCoverageRun +type CodeCoverageRun struct { + ID *int64 `json:"id,omitempty"` + TestRunPublicID *string `json:"test_run_public_id,omitempty"` +} + +// GetID returns the ID field. +// +// When the provided CodeCoverageRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageRun) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetTestRunPublicID returns the TestRunPublicID field. +// +// When the provided CodeCoverageRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageRun) GetTestRunPublicID() string { + if c == nil || c.TestRunPublicID == nil { + return "" + } + return *c.TestRunPublicID +} + +// SetID sets the ID field. +// +// When the provided CodeCoverageRun type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageRun) SetID(v int64) { + // return if CodeCoverageRun type is nil + if c == nil { + return + } + + c.ID = &v +} + +// SetTestRunPublicID sets the TestRunPublicID field. +// +// When the provided CodeCoverageRun type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageRun) SetTestRunPublicID(v string) { + // return if CodeCoverageRun type is nil + if c == nil { + return + } + + c.TestRunPublicID = &v +} diff --git a/api/types/test-report/code_coverage_stats.go b/api/types/test-report/code_coverage_stats.go new file mode 100644 index 000000000..5fce2aca8 --- /dev/null +++ b/api/types/test-report/code_coverage_stats.go @@ -0,0 +1,214 @@ +package test_report + +// CodeCoverageStats is the API types representation of code coverage stats for a pipeline. +// +// swagger:model CodeCoverageStats +type CodeCoverageStats struct { + ID *int64 `json:"id,omitempty"` + CodeCoverageRun *CodeCoverageRun `json:"code_coverage_run,omitempty"` + Scope *string `json:"scope,omitempty"` + StatementCovered *int `json:"statement_covered,omitempty"` + StatementMissed *int `json:"statement_missed,omitempty"` + LineCovered *int `json:"line_covered,omitempty"` + LineMissed *int `json:"line_missed,omitempty"` + BranchCovered *int `json:"branch_covered,omitempty"` + BranchMissed *int `json:"branch_missed,omitempty"` +} + +// GetID returns the ID field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// SetID sets the ID field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetID(v int64) { + if c == nil { + return + } + c.ID = &v +} + +// GetCodeCoverageRun returns the CodeCoverageRun field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetCodeCoverageRun() *CodeCoverageRun { + if c == nil || c.CodeCoverageRun == nil { + return new(CodeCoverageRun) + } + return c.CodeCoverageRun +} + +// SetCodeCoverageRun sets the CodeCoverageRun field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetCodeCoverageRun(v *CodeCoverageRun) { + if c == nil { + return + } + c.CodeCoverageRun = v +} + +// GetScope returns the Scope field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetScope() string { + if c == nil || c.Scope == nil { + return "" + } + return *c.Scope +} + +// SetScope sets the Scope field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetScope(v string) { + if c == nil { + return + } + c.Scope = &v +} + +// GetStatementCovered returns the StatementCovered field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetStatementCovered() int { + if c == nil || c.StatementCovered == nil { + return 0 + } + return *c.StatementCovered +} + +// SetStatementCovered sets the StatementCovered field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetStatementCovered(v int) { + if c == nil { + return + } + c.StatementCovered = &v +} + +// GetStatementMissed returns the StatementMissed field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetStatementMissed() int { + if c == nil || c.StatementMissed == nil { + return 0 + } + return *c.StatementMissed +} + +// SetStatementMissed sets the StatementMissed field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetStatementMissed(v int) { + if c == nil { + return + } + c.StatementMissed = &v +} + +// GetLineCovered returns the LineCovered field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetLineCovered() int { + if c == nil || c.LineCovered == nil { + return 0 + } + return *c.LineCovered +} + +// SetLineCovered sets the LineCovered field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetLineCovered(v int) { + if c == nil { + return + } + c.LineCovered = &v +} + +// GetLineMissed returns the LineMissed field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetLineMissed() int { + if c == nil || c.LineMissed == nil { + return 0 + } + return *c.LineMissed +} + +// SetLineMissed sets the LineMissed field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetLineMissed(v int) { + if c == nil { + return + } + c.LineMissed = &v +} + +// GetBranchCovered returns the BranchCovered field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetBranchCovered() int { + if c == nil || c.BranchCovered == nil { + return 0 + } + return *c.BranchCovered +} + +// SetBranchCovered sets the BranchCovered field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetBranchCovered(v int) { + if c == nil { + return + } + c.BranchCovered = &v +} + +// GetBranchMissed returns the BranchMissed field. +// +// When the provided CodeCoverageStats type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (c *CodeCoverageStats) GetBranchMissed() int { + if c == nil || c.BranchMissed == nil { + return 0 + } + return *c.BranchMissed +} + +// SetBranchMissed sets the BranchMissed field. +// +// When the provided CodeCoverageStats type is nil, it +// will set nothing and immediately return. +func (c *CodeCoverageStats) SetBranchMissed(v int) { + if c == nil { + return + } + c.BranchMissed = &v +} diff --git a/api/types/test-report/performance_results.go b/api/types/test-report/performance_results.go new file mode 100644 index 000000000..f29b6da7c --- /dev/null +++ b/api/types/test-report/performance_results.go @@ -0,0 +1,130 @@ +package test_report + +// PerformanceResults is the API types representation of performance results for a test run. +// +// swagger:model PerformanceResults +type PerformanceResults struct { + ID *int64 `json:"id,omitempty"` + TestRun *TestRun `json:"test_run,omitempty"` + TestRunPublicID *string `json:"test_run_public_id,omitempty"` + Name *string `json:"name,omitempty"` + RequestCount *int64 `json:"request_count,omitempty"` + RequestsPerSecond *float64 `json:"requests_per_second,omitempty"` + Average *float64 `json:"average,omitempty"` + Maximum *float64 `json:"maximum,omitempty"` + P95 *float64 `json:"p95,omitempty"` +} // GetID returns the ID field. +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetID() int64 { + // return zero value if PerformanceResults type or ID field is nil + if p == nil || p.ID == nil { + return 0 + } + + return *p.ID +} + +// GetTestRun returns the TestRun field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetTestRun() TestRun { + // return zero value if PerformanceResults type or TestRun field is nil + if p == nil || p.TestRun == nil { + return TestRun{} + } + + return *p.TestRun +} + +// GetTestRunPublicID returns the TestRunPublicID field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetTestRunPublicID() string { + // return zero value if PerformanceResults type or TestRunPublicID field is nil + if p == nil || p.TestRunPublicID == nil { + return "" + } + + return *p.TestRunPublicID +} + +// GetName returns the Name field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetName() string { + // return zero value if PerformanceResults type or Name field is nil + if p == nil || p.Name == nil { + return "" + } + + return *p.Name +} + +// GetRequestCount returns the RequestCount field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetRequestCount() int64 { + // return zero value if PerformanceResults type or RequestCount field is nil + if p == nil || p.RequestCount == nil { + return 0 + } + + return *p.RequestCount +} + +// GetRequestsPerSecond returns the RequestsPerSecond field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetRequestsPerSecond() float64 { + // return zero value if PerformanceResults type or RequestsPerSecond field is nil + if p == nil || p.RequestsPerSecond == nil { + return 0.0 + } + + return *p.RequestsPerSecond +} + +// GetAverage returns the Average field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetAverage() float64 { + // return zero value if PerformanceResults type or Average field is nil + if p == nil || p.Average == nil { + return 0.0 + } + + return *p.Average +} + +// GetMaximum returns the Maximum field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetMaximum() float64 { + // return zero value if PerformanceResults type or Maximum field is nil + if p == nil || p.Maximum == nil { + return 0.0 + } + + return *p.Maximum +} + +// GetP95 returns the P95 field. +// +// When the provided PerformanceResults type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (p *PerformanceResults) GetP95() float64 { + // return zero value if PerformanceResults type or P95 field is nil + if p == nil || p.P95 == nil { + return 0.0 + } + + return *p.P95 +} diff --git a/api/types/test-report/results_metadata.go b/api/types/test-report/results_metadata.go new file mode 100644 index 000000000..d9a33333c --- /dev/null +++ b/api/types/test-report/results_metadata.go @@ -0,0 +1,115 @@ +package test_report + +// ResultsMetadata is the API types representation of metadata for a test run. +// +// swagger:model ResultsMetadata +type ResultsMetadata struct { + ID *int64 `json:"id,omitempty"` + TestRun *TestRun `json:"test_run,omitempty"` + CI *bool `json:"ci,omitempty"` + Group *string `json:"group,omitempty"` +} + +// SetID sets the ID field. +// +// When the provided ResultsMetadata type is nil, it +// will set nothing and immediately return. +func (r *ResultsMetadata) SetID(v int64) { + // return if ResultsMetadata type is nil + if r == nil { + return + } + + r.ID = &v +} + +// GetID returns the ID field. +// +// When the provided ResultsMetadata type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsMetadata) GetID() int64 { + // return zero value if ResultsMetadata type or ID field is nil + if r == nil || r.ID == nil { + return 0 + } + + return *r.ID +} + +// SetTestRun sets the TestRun field. +// +// When the provided ResultsMetadata type is nil, it +// will set nothing and immediately return. +func (r *ResultsMetadata) SetTestRun(v TestRun) { + // return if ResultsMetadata type is nil + if r == nil { + return + } + + r.TestRun = &v +} + +// GetTestRun returns the TestRun field. +// +// When the provided ResultsMetadata type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsMetadata) GetTestRun() TestRun { + // return zero value if ResultsMetadata type or TestRun field is nil + if r == nil || r.TestRun == nil { + return TestRun{} + } + + return *r.TestRun +} + +// SetCI sets the CI field. +// +// When the provided ResultsMetadata type is nil, it +// will set nothing and immediately return. +func (r *ResultsMetadata) SetCI(v bool) { + // return if ResultsMetadata type is nil + if r == nil { + return + } + + r.CI = &v +} + +// GetCI returns the CI field. +// +// When the provided ResultsMetadata type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsMetadata) GetCI() bool { + // return zero value if ResultsMetadata type or CI field is nil + if r == nil || r.CI == nil { + return false + } + + return *r.CI +} + +// SetGroup sets the Group field. +// +// When the provided ResultsMetadata type is nil, it +// will set nothing and immediately return. +func (r *ResultsMetadata) SetGroup(v string) { + // return if ResultsMetadata type is nil + if r == nil { + return + } + + r.Group = &v +} + +// GetGroup returns the Group field. +// +// When the provided ResultsMetadata type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsMetadata) GetGroup() string { + // return zero value if ResultsMetadata type or Group field is nil + if r == nil || r.Group == nil { + return "" + } + + return *r.Group +} diff --git a/api/types/test-report/results_processing.go b/api/types/test-report/results_processing.go new file mode 100644 index 000000000..840aea5c4 --- /dev/null +++ b/api/types/test-report/results_processing.go @@ -0,0 +1,118 @@ +package test_report + +// ResultsProcessing is the API types representation of processing results for a test run. +// +// swagger:model ResultsProcessing +type ResultsProcessing struct { + ID *int64 `json:"id,omitempty"` + Status *string `json:"status,omitempty"` + ErrorMessage *string `json:"error_message,omitempty"` + Created *int64 `json:"created,omitempty"` + //Created replaced created_timestamp in Projektor model + // Following the same pattern as other fields in Vela project + // PublicID is replaced by ID for consistency across all models +} + +// SetID sets the PublicID field. +// +// When the provided ResultsProcessing type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessing) SetID(v int64) { + // return if ResultsProcessing type is nil + if r == nil { + return + } + + r.ID = &v +} + +// GetPublicID returns the PublicID field. +// +// When the provided ResultsProcessing type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessing) GetPublicID() int64 { + // return zero value if ResultsProcessing type or PublicID field is nil + if r == nil || r.ID == nil { + return 0 + } + + return *r.ID +} + +// SetStatus sets the Status field. +// +// When the provided ResultsProcessing type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessing) SetStatus(v string) { + // return if ResultsProcessing type is nil + if r == nil { + return + } + + r.Status = &v +} + +// GetStatus returns the Status field. +// +// When the provided ResultsProcessing type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessing) GetStatus() string { + // return zero value if ResultsProcessing type or Status field is nil + if r == nil || r.Status == nil { + return "" + } + + return *r.Status +} + +// SetErrorMessage sets the ErrorMessage field. +// +// When the provided ResultsProcessing type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessing) SetErrorMessage(v string) { + // return if ResultsProcessing type is nil + if r == nil { + return + } + + r.ErrorMessage = &v +} + +// GetErrorMessage returns the ErrorMessage field. +// +// When the provided ResultsProcessing type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessing) GetErrorMessage() string { + // return zero value if ResultsProcessing type or ErrorMessage field is nil + if r == nil || r.ErrorMessage == nil { + return "" + } + + return *r.ErrorMessage +} + +// SetCreated sets the Created field. +// +// When the provided ResultsProcessing type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessing) SetCreated(v int64) { + // return if ResultsProcessing type is nil + if r == nil { + return + } + + r.Created = &v +} + +// GetCreated returns the Created field. +// +// When the provided ResultsProcessing type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessing) GetCreated() int64 { + // return zero value if ResultsProcessing type or Created field is nil + if r == nil || r.Created == nil { + return 0 + } + + return *r.Created +} diff --git a/api/types/test-report/results_processing_failure.go b/api/types/test-report/results_processing_failure.go new file mode 100644 index 000000000..ad9ffd26a --- /dev/null +++ b/api/types/test-report/results_processing_failure.go @@ -0,0 +1,169 @@ +package test_report + +// ResultsProcessingFailure is the API types representation of a failure processing test results. +// +// swagger:model ResultsProcessingFailure +type ResultsProcessingFailure struct { + ID *int64 `json:"id,omitempty"` + Body *string `json:"body,omitempty"` + Created *int64 `json:"created,omitempty"` + FailureMessage *string `json:"failure_message,omitempty"` + FailureType *string `json:"failure_type,omitempty"` + BodyType *string `json:"body_type,omitempty"` +} + +// SetID sets the ID field. +// +// When the provided ResultsProcessingFailure type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessingFailure) SetID(v int64) { + // return if ResultsProcessingFailure type is nil + if r == nil { + return + } + + r.ID = &v +} + +// GetID returns the ID field. +// +// When the provided ResultsProcessingFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessingFailure) GetID() int64 { + // return zero value if ResultsProcessingFailure type or ID field is nil + if r == nil || r.ID == nil { + return 0 + } + + return *r.ID +} + +// SetBody sets the Body field. +// +// When the provided ResultsProcessingFailure type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessingFailure) SetBody(v string) { + // return if ResultsProcessingFailure type is nil + if r == nil { + return + } + + r.Body = &v +} + +// GetBody returns the Body field. +// +// When the provided ResultsProcessingFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessingFailure) GetBody() string { + // return zero value if ResultsProcessingFailure type or Body field is nil + if r == nil || r.Body == nil { + return "" + } + + return *r.Body +} + +// SetCreated sets the Created field. +// +// When the provided ResultsProcessingFailure type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessingFailure) SetCreated(v int64) { + // return if ResultsProcessingFailure type is nil + if r == nil { + return + } + + r.Created = &v +} + +// GetCreated returns the Created field. +// +// When the provided ResultsProcessingFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessingFailure) GetCreated() int64 { + // return zero value if ResultsProcessingFailure type or Created field is nil + if r == nil || r.Created == nil { + return 0 + } + + return *r.Created +} + +// SetFailureMessage sets the FailureMessage field. +// +// When the provided ResultsProcessingFailure type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessingFailure) SetFailureMessage(v string) { + // return if ResultsProcessingFailure type is nil + if r == nil { + return + } + + r.FailureMessage = &v +} + +// GetFailureMessage returns the FailureMessage field. +// +// When the provided ResultsProcessingFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessingFailure) GetFailureMessage() string { + // return zero value if ResultsProcessingFailure type or FailureMessage field is nil + if r == nil || r.FailureMessage == nil { + return "" + } + + return *r.FailureMessage +} + +// SetFailureType sets the FailureType field. +// +// When the provided ResultsProcessingFailure type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessingFailure) SetFailureType(v string) { + // return if ResultsProcessingFailure type is nil + if r == nil { + return + } + + r.FailureType = &v +} + +// GetFailureType returns the FailureType field. +// +// When the provided ResultsProcessingFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessingFailure) GetFailureType() string { + // return zero value if ResultsProcessingFailure type or FailureType field is nil + if r == nil || r.FailureType == nil { + return "" + } + + return *r.FailureType +} + +// SetBodyType sets the BodyType field. +// +// When the provided ResultsProcessingFailure type is nil, it +// will set nothing and immediately return. +func (r *ResultsProcessingFailure) SetBodyType(v string) { + // return if ResultsProcessingFailure type is nil + if r == nil { + return + } + + r.BodyType = &v +} + +// GetBodyType returns the BodyType field. +// +// When the provided ResultsProcessingFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (r *ResultsProcessingFailure) GetBodyType() string { + // return zero value if ResultsProcessingFailure type or BodyType field is nil + if r == nil || r.BodyType == nil { + return "" + } + + return *r.BodyType +} diff --git a/api/types/test-report/shedlock.go b/api/types/test-report/shedlock.go new file mode 100644 index 000000000..767b987dc --- /dev/null +++ b/api/types/test-report/shedlock.go @@ -0,0 +1,115 @@ +package test_report + +// Shedlock is the API types representation of a shedlock lock. +// +// swagger:model Shedlock +type Shedlock struct { + Name *string `json:"name,omitempty"` + LockUntil *int64 `json:"lock_until,omitempty"` + LockAt *int64 `json:"lock_at,omitempty"` + LockedBy *string `json:"locked_by,omitempty"` +} + +// SetName sets the Name field. +// +// When the provided Shedlock type is nil, it +// will set nothing and immediately return. +func (s *Shedlock) SetName(v string) { + // return if Shedlock type is nil + if s == nil { + return + } + + s.Name = &v +} + +// GetName returns the Name field. +// +// When the provided Shedlock type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (s *Shedlock) GetName() string { + // return zero value if Shedlock type or Name field is nil + if s == nil || s.Name == nil { + return "" + } + + return *s.Name +} + +// SetLockUntil sets the LockUntil field. +// +// When the provided Shedlock type is nil, it +// will set nothing and immediately return. +func (s *Shedlock) SetLockUntil(v int64) { + // return if Shedlock type is nil + if s == nil { + return + } + + s.LockUntil = &v +} + +// GetLockUntil returns the LockUntil field. +// +// When the provided Shedlock type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (s *Shedlock) GetLockUntil() int64 { + // return zero value if Shedlock type or LockUntil field is nil + if s == nil || s.LockUntil == nil { + return 0 + } + + return *s.LockUntil +} + +// SetLockAt sets the LockAt field. +// +// When the provided Shedlock type is nil, it +// will set nothing and immediately return. +func (s *Shedlock) SetLockAt(v int64) { + // return if Shedlock type is nil + if s == nil { + return + } + + s.LockAt = &v +} + +// GetLockAt returns the LockAt field. +// +// When the provided Shedlock type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (s *Shedlock) GetLockAt() int64 { + // return zero value if Shedlock type or LockAt field is nil + if s == nil || s.LockAt == nil { + return 0 + } + + return *s.LockAt +} + +// SetLockedBy sets the LockedBy field. +// +// When the provided Shedlock type is nil, it +// will set nothing and immediately return. +func (s *Shedlock) SetLockedBy(v string) { + // return if Shedlock type is nil + if s == nil { + return + } + + s.LockedBy = &v +} + +// GetLockedBy returns the LockedBy field. +// +// When the provided Shedlock type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (s *Shedlock) GetLockedBy() string { + // return zero value if Shedlock type or LockedBy field is nil + if s == nil || s.LockedBy == nil { + return "" + } + + return *s.LockedBy +} diff --git a/api/types/test-report/test_case.go b/api/types/test-report/test_case.go new file mode 100644 index 000000000..2ad1e16cc --- /dev/null +++ b/api/types/test-report/test_case.go @@ -0,0 +1,419 @@ +package test_report + +import "time" + +// TestCases is the API types representation of a test case. +// +// swagger:model TestCase + +type TestCase struct { + ID *int64 `json:"id,omitempty"` + TestSuite *TestSuite `json:"test_suite,omitempty"` + Idx *int64 `json:"idx,omitempty"` + Name *string `json:"name,omitempty"` + PackageName *string `json:"package_name,omitempty"` + ClassName *string `json:"class_name,omitempty"` + Created *int64 `json:"created,omitempty"` + Started *int64 `json:"started,omitempty"` + Finished *int64 `json:"finished,omitempty"` + Passed *bool `json:"passed,omitempty"` + Skipped *bool `json:"skipped,omitempty"` + SystemOut *string `json:"system_out,omitempty"` + SystemErr *string `json:"system_err,omitempty"` + HasSystemOut *bool `json:"has_system_out,omitempty"` + HasSystemErr *bool `json:"has_system_err,omitempty"` +} + +// Duration calculates and returns the total amount of +// time the test case ran for in a human-readable format. +func (t *TestCase) Duration() string { + // check if the test case doesn't have a started timestamp + if t.GetStarted() == 0 { + return "..." + } + + // capture started unix timestamp from the test case + started := time.Unix(t.GetStarted(), 0) + + // check if the test case doesn't have a finished timestamp + if t.GetFinished() == 0 { + // return the duration in a human-readable form by + // subtracting the test case started time from the + // current time rounded to the nearest second + return time.Since(started).Round(time.Second).String() + } + + // capture finished unix timestamp from the test case + finished := time.Unix(t.GetFinished(), 0) + + // calculate the duration by subtracting the test case + // started time from the test case finished time + duration := finished.Sub(started) + + // return the duration in a human-readable form + return duration.String() +} + +// SetID sets the ID field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetID(v int64) { + // return if TestCase type is nil + if t == nil { + return + } + + t.ID = &v +} + +// GetID returns the ID field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetID() int64 { + // return zero value if TestCase type or ID field is nil + if t == nil || t.ID == nil { + return 0 + } + + return *t.ID +} + +// SetIdx sets the Idx field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetIdx(v int64) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Idx = &v +} + +// GetIdx returns the Idx field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetIdx() int64 { + // return zero value if TestCase type or Idx field is nil + if t == nil || t.Idx == nil { + return 0 + } + + return *t.Idx +} + +// SetName sets the Name field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetName(v string) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Name = &v +} + +// GetName returns the Name field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetName() string { + // return zero value if TestCase type or Name field is nil + if t == nil || t.Name == nil { + return "" + } + + return *t.Name +} + +// SetPackageName sets the PackageName field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetPackageName(v string) { + // return if TestCase type is nil + if t == nil { + return + } + + t.PackageName = &v +} + +// GetPackageName returns the PackageName field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetPackageName() string { + // return zero value if TestCase type or PackageName field is nil + if t == nil || t.PackageName == nil { + return "" + } + + return *t.PackageName +} + +// SetClassName sets the ClassName field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetClassName(v string) { + // return if TestCase type is nil + if t == nil { + return + } + + t.ClassName = &v +} + +// GetClassName returns the ClassName field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetClassName() string { + // return zero value if TestCase type or ClassName field is nil + if t == nil || t.ClassName == nil { + return "" + } + + return *t.ClassName +} + +// SetCreated sets the Created field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetCreated(v int64) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Created = &v +} + +// GetCreated returns the Created field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetCreated() int64 { + // return zero value if TestCase type or Created field is nil + if t == nil || t.Created == nil { + return 0 + } + + return *t.Created +} + +// SetStarted sets the Started field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetStarted(v int64) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Started = &v +} + +// GetStarted returns the Started field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetStarted() int64 { + // return zero value if TestCase type or Started field is nil + if t == nil || t.Started == nil { + return 0 + } + + return *t.Started +} + +// SetFinished sets the Finished field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetFinished(v int64) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Finished = &v +} + +// GetFinished returns the Finished field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetFinished() int64 { + // return zero value if TestCase type or Finished field is nil + if t == nil || t.Finished == nil { + return 0 + } + + return *t.Finished +} + +// SetPassed sets the Passed field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetPassed(v bool) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Passed = &v +} + +// GetPassed returns the Passed field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetPassed() bool { + // return zero value if TestCase type or Passed field is nil + if t == nil || t.Passed == nil { + return false + } + + return *t.Passed +} + +// SetSkipped sets the Skipped field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetSkipped(v bool) { + // return if TestCase type is nil + if t == nil { + return + } + + t.Skipped = &v +} + +// GetSkipped returns the Skipped field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetSkipped() bool { + // return zero value if TestCase type or Skipped field is nil + if t == nil || t.Skipped == nil { + return false + } + + return *t.Skipped +} + +// SetSystemOut sets the SystemOut field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetSystemOut(v string) { + // return if TestCase type is nil + if t == nil { + return + } + + t.SystemOut = &v +} + +// GetSystemOut returns the SystemOut field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetSystemOut() string { + // return zero value if TestCase type or SystemOut field is nil + if t == nil || t.SystemOut == nil { + return "" + } + + return *t.SystemOut +} + +// SetSystemErr sets the SystemErr field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetSystemErr(v string) { + // return if TestCase type is nil + if t == nil { + return + } + + t.SystemErr = &v +} + +// GetSystemErr returns the SystemErr field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetSystemErr() string { + // return zero value if TestCase type or SystemErr field is nil + if t == nil || t.SystemErr == nil { + return "" + } + + return *t.SystemErr +} + +// SetHasSystemOut sets the HasSystemOut field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetHasSystemOut(v bool) { + // return if TestCase type is nil + if t == nil { + return + } + + t.HasSystemOut = &v +} + +// GetHasSystemOut returns the HasSystemOut field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetHasSystemOut() bool { + // return zero value if TestCase type or HasSystemOut field is nil + if t == nil || t.HasSystemOut == nil { + return false + } + + return *t.HasSystemOut +} + +// SetHasSystemErr sets the HasSystemErr field. +// +// When the provided TestCase type is nil, it +// will set nothing and immediately return. +func (t *TestCase) SetHasSystemErr(v bool) { + // return if TestCase type is nil + if t == nil { + return + } + + t.HasSystemErr = &v +} + +// GetHasSystemErr returns the HasSystemErr field. +// +// When the provided TestCase type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestCase) GetHasSystemErr() bool { + // return zero value if TestCase type or HasSystemErr field is nil + if t == nil || t.HasSystemErr == nil { + return false + } + + return *t.HasSystemErr +} diff --git a/api/types/test-report/test_failure.go b/api/types/test-report/test_failure.go new file mode 100644 index 000000000..62cc83dfb --- /dev/null +++ b/api/types/test-report/test_failure.go @@ -0,0 +1,132 @@ +package test_report + +// TestFailure is the API types representation of a test for a pipeline. +// +// swagger:model TestFailure +type TestFailure struct { + ID *int64 `json:"id,omitempty"` + TestCaseID *int64 `json:"test_case_id,omitempty"` + FailureMessage *string `json:"failure_message,omitempty"` + FailureType *string `json:"failure_type,omitempty"` + FailureText *string `json:"failure_text,omitempty"` +} + +// GetID returns the ID field. +// +// When the provided TestFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestFailure) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetTestCaseID returns the TestCaseID field. +// +// When the provided TestFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestFailure) GetTestCaseID() int64 { + if t == nil || t.TestCaseID == nil { + return 0 + } + return *t.TestCaseID +} + +// GetFailureMessage returns the FailureMessage field. +// +// When the provided TestFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestFailure) GetFailureMessage() string { + if t == nil || t.FailureMessage == nil { + return "" + } + return *t.FailureMessage +} + +// GetFailureType returns the FailureType field. +// +// When the provided TestFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestFailure) GetFailureType() string { + if t == nil || t.FailureType == nil { + return "" + } + return *t.FailureType +} + +// GetFailureText returns the FailureText field. +// +// When the provided TestFailure type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestFailure) GetFailureText() string { + if t == nil || t.FailureText == nil { + return "" + } + return *t.FailureText +} + +// SetID sets the ID field. +// +// When the provided TestFailure type is nil, it +// will set nothing and immediately return. +func (t *TestFailure) SetID(v int64) { + // return if TestFailure type is nil + if t == nil { + return + } + + t.ID = &v +} + +// SetTestCaseID sets the TestCaseID field. +// +// When the provided TestFailure type is nil, it +// will set nothing and immediately return. +func (t *TestFailure) SetTestCaseID(v int64) { + // return if TestFailure type is nil + if t == nil { + return + } + + t.TestCaseID = &v +} + +// SetFailureMessage sets the FailureMessage field. +// +// When the provided TestFailure type is nil, it +// will set nothing and immediately return. +func (t *TestFailure) SetFailureMessage(v string) { + // return if TestFailure type is nil + if t == nil { + return + } + + t.FailureMessage = &v +} + +// SetFailureType sets the FailureType field. +// +// When the provided TestFailure type is nil, it +// will set nothing and immediately return. +func (t *TestFailure) SetFailureType(v string) { + // return if TestFailure type is nil + if t == nil { + return + } + + t.FailureType = &v +} + +// SetFailureText sets the FailureText field. +// +// When the provided TestFailure type is nil, it +// will set nothing and immediately return. +func (t *TestFailure) SetFailureText(v string) { + // return if TestFailure type is nil + if t == nil { + return + } + + t.FailureText = &v +} diff --git a/api/types/test-report/test_run.go b/api/types/test-report/test_run.go new file mode 100644 index 000000000..2e9eaee52 --- /dev/null +++ b/api/types/test-report/test_run.go @@ -0,0 +1,319 @@ +package test_report + +import "time" + +// TestRun is the API types representation of a test run for a pipeline. +// +// swagger:model TestRun +type TestRun struct { + ID *int64 `json:"id,omitempty"` + TestRunSystemAttributes *TestRunSystemAttributes `json:"test_run_system_attributes,omitempty"` + TotalTestCount *int `json:"total_test_count,omitempty"` + TotalPassingCount *int `json:"total_passing_count,omitempty"` + TotalSkipCount *int `json:"total_skip_count,omitempty"` + TotalFailureCount *int `json:"total_failure_count,omitempty"` + Passed *bool `json:"passed,omitempty"` + Created *int64 `json:"created,omitempty"` + Started *int64 `json:"started,omitempty"` + Finished *int64 `json:"finished,omitempty"` + AverageDuration *int64 `json:"average_duration,omitempty"` + SlowestTestCaseDuration *int64 `json:"slowest_test_case_duration,omitempty"` + WallClockDuration *int64 `json:"wall_clock_duration,omitempty"` +} + +// In Vela, int64 is used to stored Unix timestamps instead of float64 for time.Time +// created_timestamp is replaced by Created +// Original Projektor model has cumulative_duration field which is not present in this model +// Created, Started, Finished are Vela standard model fields +// AverageDuration, SlowestTestCaseDuration, WallClockDuration might be taken out and calculated on the fly +// like in the Duration method + +// Duration calculates and returns the total amount of +// time the build ran for in a human-readable format. +func (b *TestRun) Duration() string { + // check if the build doesn't have a started timestamp + if b.GetStarted() == 0 { + return "..." + } + + // capture started unix timestamp from the build + started := time.Unix(b.GetStarted(), 0) + + // check if the build doesn't have a finished timestamp + if b.GetFinished() == 0 { + // return the duration in a human-readable form by + // subtracting the build started time from the + // current time rounded to the nearest second + return time.Since(started).Round(time.Second).String() + } + + // capture finished unix timestamp from the build + finished := time.Unix(b.GetFinished(), 0) + + // calculate the duration by subtracting the build + // started time from the build finished time + duration := finished.Sub(started) + + // return the duration in a human-readable form + return duration.String() +} + +// GetID returns the ID field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetID() int64 { + // return zero value if TestRun type or ID field is nil + if b == nil || b.ID == nil { + return 0 + } + return *b.ID +} + +// SetID sets the ID field. +func (b *TestRun) SetID(v int64) { + if b == nil { + return + } + b.ID = &v +} + +// GetTestRunSystemAttributes returns the TestRunSystemAttributes field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetTestRunSystemAttributes() TestRunSystemAttributes { + // return zero value if TestRun type or TestRunSystemAttributes field is nil + if b == nil || b.TestRunSystemAttributes == nil { + return TestRunSystemAttributes{} + } + return *b.TestRunSystemAttributes +} + +// SetTestRunSystemAttributes sets the TestRunSystemAttributes field. +func (b *TestRun) SetTestRunSystemAttributes(v TestRunSystemAttributes) { + if b == nil { + return + } + b.TestRunSystemAttributes = &v +} + +// GetTotalTestCount returns the TotalTestCount field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetTotalTestCount() int { + // return zero value if TestRun type or TotalTestCount field is nil + if b == nil || b.TotalTestCount == nil { + return 0 + } + return *b.TotalTestCount +} + +// SetTotalTestCount sets the TotalTestCount field. +func (b *TestRun) SetTotalTestCount(v int) { + if b == nil { + return + } + b.TotalTestCount = &v +} + +// GetTotalPassingCount returns the TotalPassingCount field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetTotalPassingCount() int { + // return zero value if TestRun type or TotalPassingCount field is nil + if b == nil || b.TotalPassingCount == nil { + return 0 + } + return *b.TotalPassingCount +} + +// SetTotalPassingCount sets the TotalPassingCount field. +func (b *TestRun) SetTotalPassingCount(v int) { + if b == nil { + return + } + b.TotalPassingCount = &v +} + +// GetTotalSkipCount returns the TotalSkipCount field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetTotalSkipCount() int { + // return zero value if TestRun type or TotalSkipCount field is nil + if b == nil || b.TotalSkipCount == nil { + return 0 + } + return *b.TotalSkipCount +} + +// SetTotalSkipCount sets the TotalSkipCount field. +func (b *TestRun) SetTotalSkipCount(v int) { + if b == nil { + return + } + b.TotalSkipCount = &v +} + +// GetTotalFailureCount returns the TotalFailureCount field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetTotalFailureCount() int { + // return zero value if TestRun type or TotalFailureCount field is nil + if b == nil || b.TotalFailureCount == nil { + return 0 + } + return *b.TotalFailureCount +} + +// SetTotalFailureCount sets the TotalFailureCount field. +func (b *TestRun) SetTotalFailureCount(v int) { + if b == nil { + return + } + b.TotalFailureCount = &v +} + +// GetPassed returns the Passed field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetPassed() bool { + // return zero value if TestRun type or Passed field is nil + if b == nil || b.Passed == nil { + return false + } + return *b.Passed +} + +// SetPassed sets the Passed field. +func (b *TestRun) SetPassed(v bool) { + if b == nil { + return + } + b.Passed = &v +} + +// GetCreated returns the Created field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetCreated() int64 { + // return zero value if TestRun type or Created field is nil + if b == nil || b.Created == nil { + return 0 + } + return *b.Created +} + +// SetCreated sets the Created field. +func (b *TestRun) SetCreated(v int64) { + if b == nil { + return + } + b.Created = &v +} + +// GetStarted returns the Started field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetStarted() int64 { + // return zero value if TestRun type or Started field is nil + if b == nil || b.Started == nil { + return 0 + } + return *b.Started +} + +// SetStarted sets the Started field. +func (b *TestRun) SetStarted(v int64) { + if b == nil { + return + } + b.Started = &v +} + +// GetFinished returns the Finished field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetFinished() int64 { + // return zero value if TestRun type or Finished field is nil + if b == nil || b.Finished == nil { + return 0 + } + return *b.Finished +} + +// SetFinished sets the Finished field. +func (b *TestRun) SetFinished(v int64) { + if b == nil { + return + } + b.Finished = &v +} + +// GetAverageDuration returns the AverageDuration field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetAverageDuration() int64 { + // return zero value if TestRun type or AverageDuration field is nil + if b == nil || b.AverageDuration == nil { + return 0 + } + return *b.AverageDuration +} + +// SetAverageDuration sets the AverageDuration field. +func (b *TestRun) SetAverageDuration(v int64) { + if b == nil { + return + } + b.AverageDuration = &v +} + +// GetSlowestTestCaseDuration returns the SlowestTestCaseDuration field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetSlowestTestCaseDuration() int64 { + // return zero value if TestRun type or SlowestTestCaseDuration field is nil + if b == nil || b.SlowestTestCaseDuration == nil { + return 0 + } + return *b.SlowestTestCaseDuration +} + +// SetSlowestTestCaseDuration sets the SlowestTestCaseDuration field. +func (b *TestRun) SetSlowestTestCaseDuration(v int64) { + if b == nil { + return + } + b.SlowestTestCaseDuration = &v +} + +// GetWallClockDuration returns the WallClockDuration field. +// +// When the provided TestRun type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRun) GetWallClockDuration() int64 { + // return zero value if TestRun type or WallClockDuration field is nil + if b == nil || b.WallClockDuration == nil { + return 0 + } + return *b.WallClockDuration +} + +// SetWallClockDuration sets the WallClockDuration field. +func (b *TestRun) SetWallClockDuration(v int64) { + if b == nil { + return + } + b.WallClockDuration = &v +} diff --git a/api/types/test-report/test_run_attachment.go b/api/types/test-report/test_run_attachment.go new file mode 100644 index 000000000..c5ca02d7e --- /dev/null +++ b/api/types/test-report/test_run_attachment.go @@ -0,0 +1,11 @@ +package test_report + +// TestRunAttachment is the API types representation of an attachment for a test run. +// +// swagger:model TestRunAttachment +type TestRunAttachment struct { + ID *int64 `json:"id,omitempty"` + FileName *string `json:"file_name,omitempty"` + ObjectName *string `json:"object_name,omitempty"` + FileSize *int64 `json:"file_size,omitempty"` +} diff --git a/api/types/test-report/test_run_system_attributes.go b/api/types/test-report/test_run_system_attributes.go new file mode 100644 index 000000000..6efb5ad9a --- /dev/null +++ b/api/types/test-report/test_run_system_attributes.go @@ -0,0 +1,47 @@ +package test_report + +// TestRunSystemAttributes is the API types representation of system attributes for a test run. +// +// swagger:model TestRunSystemAttributes +type TestRunSystemAttributes struct { + ID *int64 `json:"id,omitempty"` + Pinned *bool `json:"pinned,omitempty"` +} + +// GetID returns the ID field. +// +// When the provided TestRunSystemAttributes type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRunSystemAttributes) GetID() int64 { + if b == nil || b.ID == nil { + return 0 + } + return *b.ID +} + +// SetID sets the ID field. +func (b *TestRunSystemAttributes) SetID(v int64) { + if b == nil { + return + } + b.ID = &v +} + +// GetPinned returns the Pinned field. +// +// When the provided TestRunSystemAttributes type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (b *TestRunSystemAttributes) GetPinned() bool { + if b == nil || b.Pinned == nil { + return false + } + return *b.Pinned +} + +// SetPinned sets the Pinned field. +func (b *TestRunSystemAttributes) SetPinned(v bool) { + if b == nil { + return + } + b.Pinned = &v +} diff --git a/api/types/test-report/test_suite.go b/api/types/test-report/test_suite.go new file mode 100644 index 000000000..6ad451f48 --- /dev/null +++ b/api/types/test-report/test_suite.go @@ -0,0 +1,552 @@ +package test_report + +import "time" + +// TestSuite is the API types representation of a test suite for a test run. +// +// swagger:model TestSuite +type TestSuite struct { + ID *int64 `json:"id,omitempty"` + TestRun *TestRun `json:"test_run,omitempty"` + TestSuiteGroup *TestSuiteGroup `json:"test_suite_group,omitempty"` + Idx *int64 `json:"idx,omitempty"` + PackageName *string `json:"package_name,omitempty"` + ClassName *string `json:"class_name,omitempty"` + TestCount *int64 `json:"test_count,omitempty"` + PassingCount *int64 `json:"passing_count,omitempty"` + SkippedCount *int64 `json:"skipped_count,omitempty"` + FailureCount *int64 `json:"failure_count,omitempty"` + StartTs *int64 `json:"start_ts,omitempty"` + Hostname *string `json:"hostname,omitempty"` + Started *int64 `json:"started,omitempty"` + Finished *int64 `json:"finished,omitempty"` + SystemOut *string `json:"system_out,omitempty"` + SystemErr *string `json:"system_err,omitempty"` + HasSystemOut *bool `json:"has_system_out,omitempty"` + HasSystemErr *bool `json:"has_system_err,omitempty"` + FileName *string `json:"file_name,omitempty"` +} + +// Duration calculates and returns the total amount of +// time the test suite ran for in a human-readable format. +func (t *TestSuite) Duration() string { + // check if the test suite doesn't have a started timestamp + if t.GetStarted() == 0 { + return "..." + } + + // capture started unix timestamp from the test suite + started := time.Unix(t.GetStarted(), 0) + + // check if the test suite doesn't have a finished timestamp + if t.GetFinished() == 0 { + // return the duration in a human-readable form by + // subtracting the test suite started time from the + // current time rounded to the nearest second + return time.Since(started).Round(time.Second).String() + } + + // capture finished unix timestamp from the test suite + finished := time.Unix(t.GetFinished(), 0) + + // calculate the duration by subtracting the test suite + // started time from the test suite finished time + duration := finished.Sub(started) + + // return the duration in a human-readable form + return duration.String() +} + +// SetID sets the ID field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetID(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.ID = &v +} + +// GetID returns the ID field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetID() int64 { + // return zero value if TestSuite type or ID field is nil + if t == nil || t.ID == nil { + return 0 + } + + return *t.ID +} + +// SetTestRun sets the TestRun field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetTestRun(v TestRun) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.TestRun = &v +} + +// GetTestRun returns the TestRun field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetTestRun() TestRun { + // return zero value if TestSuite type or TestRun field is nil + if t == nil || t.TestRun == nil { + return TestRun{} + } + + return *t.TestRun +} + +// SetTestSuiteGroup sets the TestSuiteGroup field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetTestSuiteGroup(v TestSuiteGroup) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.TestSuiteGroup = &v +} + +// GetTestSuiteGroup returns the TestSuiteGroup field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetTestSuiteGroup() TestSuiteGroup { + // return zero value if TestSuite type or TestSuiteGroup field is nil + if t == nil || t.TestSuiteGroup == nil { + return TestSuiteGroup{} + } + + return *t.TestSuiteGroup +} + +// SetIdx sets the Idx field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetIdx(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.Idx = &v +} + +// GetIdx returns the Idx field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetIdx() int64 { + // return zero value if TestSuite type or Idx field is nil + if t == nil || t.Idx == nil { + return 0 + } + + return *t.Idx +} + +// SetPackageName sets the PackageName field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetPackageName(v string) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.PackageName = &v +} + +// GetPackageName returns the PackageName field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetPackageName() string { + // return zero value if TestSuite type or PackageName field is nil + if t == nil || t.PackageName == nil { + return "" + } + + return *t.PackageName +} + +// SetClassName sets the ClassName field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetClassName(v string) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.ClassName = &v +} + +// GetClassName returns the ClassName field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetClassName() string { + // return zero value if TestSuite type or ClassName field is nil + if t == nil || t.ClassName == nil { + return "" + } + + return *t.ClassName +} + +// SetTestCount sets the TestCount field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetTestCount(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.TestCount = &v +} + +// GetTestCount returns the TestCount field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetTestCount() int64 { + // return zero value if TestSuite type or TestCount field is nil + if t == nil || t.TestCount == nil { + return 0 + } + + return *t.TestCount +} + +// SetPassingCount sets the PassingCount field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetPassingCount(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.PassingCount = &v +} + +// GetPassingCount returns the PassingCount field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetPassingCount() int64 { + // return zero value if TestSuite type or PassingCount field is nil + if t == nil || t.PassingCount == nil { + return 0 + } + + return *t.PassingCount +} + +// SetSkippedCount sets the SkippedCount field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetSkippedCount(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.SkippedCount = &v +} + +// GetSkippedCount returns the SkippedCount field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetSkippedCount() int64 { + // return zero value if TestSuite type or SkippedCount field is nil + if t == nil || t.SkippedCount == nil { + return 0 + } + + return *t.SkippedCount +} + +// SetFailureCount sets the FailureCount field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetFailureCount(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.FailureCount = &v +} + +// GetFailureCount returns the FailureCount field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetFailureCount() int64 { + // return zero value if TestSuite type or FailureCount field is nil + if t == nil || t.FailureCount == nil { + return 0 + } + + return *t.FailureCount +} + +// SetStartTs sets the StartTs field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetStartTs(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.StartTs = &v +} + +// GetStartTs returns the StartTs field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetStartTs() int64 { + // return zero value if TestSuite type or StartTs field is nil + if t == nil || t.StartTs == nil { + return 0 + } + + return *t.StartTs +} + +// SetHostname sets the Hostname field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetHostname(v string) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.Hostname = &v +} + +// GetHostname returns the Hostname field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetHostname() string { + // return zero value if TestSuite type or Hostname field is nil + if t == nil || t.Hostname == nil { + return "" + } + + return *t.Hostname +} + +// SetStarted sets the Started field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetStarted(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.Started = &v +} + +// GetStarted returns the Started field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetStarted() int64 { + // return zero value if TestSuite type or Started field is nil + if t == nil || t.Started == nil { + return 0 + } + + return *t.Started +} + +// SetFinished sets the Finished field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetFinished(v int64) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.Finished = &v +} + +// GetFinished returns the Finished field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetFinished() int64 { + // return zero value if TestSuite type or Finished field is nil + if t == nil || t.Finished == nil { + return 0 + } + + return *t.Finished +} + +// SetSystemOut sets the SystemOut field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetSystemOut(v string) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.SystemOut = &v +} + +// GetSystemOut returns the SystemOut field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetSystemOut() string { + // return zero value if TestSuite type or SystemOut field is nil + if t == nil || t.SystemOut == nil { + return "" + } + + return *t.SystemOut +} + +// SetSystemErr sets the SystemErr field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetSystemErr(v string) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.SystemErr = &v +} + +// GetSystemErr returns the SystemErr field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetSystemErr() string { + // return zero value if TestSuite type or SystemErr field is nil + if t == nil || t.SystemErr == nil { + return "" + } + + return *t.SystemErr +} + +// SetHasSystemOut sets the HasSystemOut field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetHasSystemOut(v bool) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.HasSystemOut = &v +} + +// GetHasSystemOut returns the HasSystemOut field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetHasSystemOut() bool { + // return zero value if TestSuite type or HasSystemOut field is nil + if t == nil || t.HasSystemOut == nil { + return false + } + + return *t.HasSystemOut +} + +// SetHasSystemErr sets the HasSystemErr field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetHasSystemErr(v bool) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.HasSystemErr = &v +} + +// GetHasSystemErr returns the HasSystemErr field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetHasSystemErr() bool { + // return zero value if TestSuite type or HasSystemErr field is nil + if t == nil || t.HasSystemErr == nil { + return false + } + + return *t.HasSystemErr +} + +// SetFileName sets the FileName field. +// +// When the provided TestSuite type is nil, it +// will set nothing and immediately return. +func (t *TestSuite) SetFileName(v string) { + // return if TestSuite type is nil + if t == nil { + return + } + + t.FileName = &v +} + +// GetFileName returns the FileName field. +// +// When the provided TestSuite type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuite) GetFileName() string { + // return zero value if TestSuite type or FileName field is nil + if t == nil || t.FileName == nil { + return "" + } + + return *t.FileName +} diff --git a/api/types/test-report/test_suite_group.go b/api/types/test-report/test_suite_group.go new file mode 100644 index 000000000..78ccc1d8f --- /dev/null +++ b/api/types/test-report/test_suite_group.go @@ -0,0 +1,142 @@ +package test_report + +// TestSuiteGroup is the API types representation of a group of test suites for a test run. +// +// swagger:model TestSuiteGroup +type TestSuiteGroup struct { + ID *int64 `json:"id,omitempty"` + TestRun *TestRun `json:"test_run,omitempty"` + GroupName *string `json:"group_name,omitempty"` + GroupLabel *string `json:"group_label,omitempty"` + Directory *string `json:"directory,omitempty"` +} + +// SetID sets the ID field. +// +// When the provided TestSuiteGroup type is nil, it +// will set nothing and immediately return. +func (t *TestSuiteGroup) SetID(v int64) { + // return if TestSuiteGroup type is nil + if t == nil { + return + } + + t.ID = &v +} + +// GetID returns the ID field. +// +// When the provided TestSuiteGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuiteGroup) GetID() int64 { + // return zero value if TestSuiteGroup type or ID field is nil + if t == nil || t.ID == nil { + return 0 + } + + return *t.ID +} + +// SetTestRun sets the TestRun field. +// +// When the provided TestSuiteGroup type is nil, it +// will set nothing and immediately return. +func (t *TestSuiteGroup) SetTestRun(v TestRun) { + // return if TestSuiteGroup type is nil + if t == nil { + return + } + + t.TestRun = &v +} + +// GetTestRun returns the TestRun field. +// +// When the provided TestSuiteGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuiteGroup) GetTestRun() TestRun { + // return zero value if TestSuiteGroup type or TestRun field is nil + if t == nil || t.TestRun == nil { + return TestRun{} + } + + return *t.TestRun +} + +// SetGroupName sets the GroupName field. +// +// When the provided TestSuiteGroup type is nil, it +// will set nothing and immediately return. +func (t *TestSuiteGroup) SetGroupName(v string) { + // return if TestSuiteGroup type is nil + if t == nil { + return + } + + t.GroupName = &v +} + +// GetGroupName returns the GroupName field. +// +// When the provided TestSuiteGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuiteGroup) GetGroupName() string { + // return zero value if TestSuiteGroup type or GroupName field is nil + if t == nil || t.GroupName == nil { + return "" + } + + return *t.GroupName +} + +// SetGroupLabel sets the GroupLabel field. +// +// When the provided TestSuiteGroup type is nil, it +// will set nothing and immediately return. +func (t *TestSuiteGroup) SetGroupLabel(v string) { + // return if TestSuiteGroup type is nil + if t == nil { + return + } + + t.GroupLabel = &v +} + +// GetGroupLabel returns the GroupLabel field. +// +// When the provided TestSuiteGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuiteGroup) GetGroupLabel() string { + // return zero value if TestSuiteGroup type or GroupLabel field is nil + if t == nil || t.GroupLabel == nil { + return "" + } + + return *t.GroupLabel +} + +// SetDirectory sets the Directory field. +// +// When the provided TestSuiteGroup type is nil, it +// will set nothing and immediately return. +func (t *TestSuiteGroup) SetDirectory(v string) { + // return if TestSuiteGroup type is nil + if t == nil { + return + } + + t.Directory = &v +} + +// GetDirectory returns the Directory field. +// +// When the provided TestSuiteGroup type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (t *TestSuiteGroup) GetDirectory() string { + // return zero value if TestSuiteGroup type or Directory field is nil + if t == nil || t.Directory == nil { + return "" + } + + return *t.Directory +} diff --git a/cmd/vela-server/main.go b/cmd/vela-server/main.go index 5af8a852c..27f1a2ff1 100644 --- a/cmd/vela-server/main.go +++ b/cmd/vela-server/main.go @@ -5,6 +5,7 @@ package main import ( "encoding/json" "fmt" + "github.com/go-vela/server/ex-storage" "os" "time" @@ -283,6 +284,9 @@ func main() { // Add Tracing Flags app.Flags = append(app.Flags, tracing.Flags...) + // Add S3 Flags + app.Flags = append(app.Flags, ex_storage.Flags...) + if err = app.Run(os.Args); err != nil { logrus.Fatal(err) } diff --git a/cmd/vela-server/server.go b/cmd/vela-server/server.go index 7733b9c15..90e98d78a 100644 --- a/cmd/vela-server/server.go +++ b/cmd/vela-server/server.go @@ -6,6 +6,7 @@ import ( "context" "errors" "fmt" + "github.com/go-vela/server/ex-storage" "net/http" "net/url" "os" @@ -93,6 +94,11 @@ func server(c *cli.Context) error { }() } + st, err := ex_storage.FromCLIContext(c) + if err != nil { + return err + } + database, err := database.FromCLIContext(c, tc) if err != nil { return err diff --git a/constants/driver.go b/constants/driver.go index e42b924c5..fb716e435 100644 --- a/constants/driver.go +++ b/constants/driver.go @@ -62,3 +62,11 @@ const ( // DriverGitLab defines the driver type when integrating with a Gitlab source code system. DriverGitlab = "gitlab" ) + +// Server storage drivers. +const ( + // DriverMinio defines the driver type when integrating with a local storage system. + DriverMinio = "minio" + // DriverAws defines the driver type when integrating with an AWS S3 storage system. + DriverAws = "aws" +) diff --git a/docker-compose.yml b/docker-compose.yml index a96b4b87f..74e5a2a34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -179,5 +179,15 @@ services: - '16686:16686' - '4318:4318' + objectstorage: + image: bitnami/minio:2020.12.29-debian-10-r17 + ports: + - "9000:9000" + volumes: + - ./minio:/data + environment: + MINIO_ACCESS_KEY: minio_access_key + MINIO_SECRET_KEY: minio_secret_key + networks: vela: diff --git a/go.mod b/go.mod index 290078d95..5b6df7662 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,9 @@ require ( github.com/adhocore/gronx v1.19.1 github.com/alicebob/miniredis/v2 v2.33.0 github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go-v2/config v1.28.6 + github.com/aws/aws-sdk-go-v2/credentials v1.17.47 + github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 github.com/distribution/reference v0.6.0 github.com/drone/envsubst v1.0.3 @@ -29,6 +32,7 @@ require ( github.com/lestrrat-go/jwx/v2 v2.1.1 github.com/lib/pq v1.10.9 github.com/microcosm-cc/bluemonday v1.0.27 + github.com/minio/minio-go/v7 v7.0.81 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.4 github.com/redis/go-redis/v9 v9.6.1 @@ -45,7 +49,7 @@ require ( go.opentelemetry.io/otel/sdk v1.30.0 go.opentelemetry.io/otel/trace v1.30.0 go.starlark.net v0.0.0-20240925182052-1207426daebd - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 golang.org/x/time v0.6.0 @@ -61,6 +65,21 @@ require ( github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect + github.com/aws/aws-sdk-go-v2 v1.32.6 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 // indirect + github.com/aws/smithy-go v1.22.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.12.2 // indirect @@ -72,10 +91,12 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.5 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -104,7 +125,7 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect @@ -114,6 +135,7 @@ require ( github.com/lestrrat-go/option v1.0.1 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -126,6 +148,7 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect + github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/segmentio/asm v1.2.0 // indirect @@ -140,9 +163,9 @@ require ( go.opentelemetry.io/otel/metric v1.30.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect golang.org/x/arch v0.10.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/grpc v1.66.1 // indirect diff --git a/go.sum b/go.sum index 1957fb598..9432f2853 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,42 @@ github.com/alicebob/miniredis/v2 v2.33.0/go.mod h1:MhP4a3EU7aENRi9aO+tHfTBZicLqQ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= +github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= +github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= +github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25 h1:r67ps7oHCYnflpgDy2LZU0MAQtQbYIOqNNnqGO6xQkE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25/go.mod h1:GrGY+Q4fIokYLtjCVB/aFfCVL6hhGUFl8inD18fDalE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6 h1:HCpPsWqmYQieU7SS6E9HXfdAMSud0pteVXieJmcpIRI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6/go.mod h1:ngUiVRCco++u+soRRVBIvBZxSMMvOVMXA4PJ36JLfSw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 h1:BbGDtTi0T1DYlmjBiCr/le3wzhA37O8QTC5/Ab8+EXk= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6/go.mod h1:hLMJt7Q8ePgViKupeymbqI0la+t9/iYFBjxQCFwuAwI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPxhtt4DcBIHyCnmw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -68,6 +104,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g= github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= @@ -85,6 +123,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -181,8 +221,9 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -221,6 +262,10 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.81 h1:SzhMN0TQ6T/xSBu6Nvw3M5M8voM+Ht8RH3hE8S7zxaA= +github.com/minio/minio-go/v7 v7.0.81/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -261,6 +306,8 @@ github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0 github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -336,8 +383,8 @@ golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -345,8 +392,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -362,12 +409,12 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/storage/context.go b/storage/context.go new file mode 100644 index 000000000..411ba4412 --- /dev/null +++ b/storage/context.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 + +package storage + +import ( + "context" + "github.com/gin-gonic/gin" +) + +// key is the key used to store minio service in context +const key = "minio" + +// FromContext retrieves minio service from the context +func FromContext(ctx context.Context) Storage { + // get minio value from context.Context + v := ctx.Value(key) + if v == nil { + return nil + } + + // cast minio value to expected Storage type + s, ok := v.(Storage) + if !ok { + return nil + } + return s +} + +// FromGinContext retrieves the S3 Service from the gin.Context. +func FromGinContext(c *gin.Context) Storage { + // get minio value from gin.Context + // + // https://pkg.go.dev/github.com/gin-gonic/gin?tab=doc#Context.Get + v, ok := c.Get(key) + if !ok { + return nil + } + + // cast minio value to expected Service type + s, ok := v.(Storage) + if !ok { + return nil + } + + return s +} + +// WithContext adds the minio Storage to the context +func WithContext(ctx context.Context, storage Storage) context.Context { + return context.WithValue(ctx, key, storage) +} + +// WithGinContext inserts the minio Storage into the gin.Context. +func WithGinContext(c *gin.Context, s Storage) { + // set the minio Storage in the gin.Context + // + // https://pkg.go.dev/github.com/gin-gonic/gin?tab=doc#Context.Set + c.Set(key, s) +} diff --git a/storage/context_test.go b/storage/context_test.go new file mode 100644 index 000000000..9b96d83b9 --- /dev/null +++ b/storage/context_test.go @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: Apache-2.0 + +package storage + +import ( + "context" + "reflect" + "testing" + + "github.com/gin-gonic/gin" +) + +func TestExecutor_FromContext(t *testing.T) { + // setup types + _service, _ := New(&Setup{}) + + // setup tests + tests := []struct { + context context.Context + want Storage + }{ + { + //nolint:staticcheck,revive // ignore using string with context value + context: context.WithValue(context.Background(), key, _service), + want: _service, + }, + { + context: context.Background(), + want: nil, + }, + { + //nolint:staticcheck,revive // ignore using string with context value + context: context.WithValue(context.Background(), key, "foo"), + want: nil, + }, + } + + // run tests + for _, test := range tests { + got := FromContext(test.context) + + if !reflect.DeepEqual(got, test.want) { + t.Errorf("FromContext is %v, want %v", got, test.want) + } + } +} + +func TestExecutor_FromGinContext(t *testing.T) { + // setup types + _service, _ := New(&Setup{}) + + // setup tests + tests := []struct { + context *gin.Context + value interface{} + want Storage + }{ + { + context: new(gin.Context), + value: _service, + want: _service, + }, + { + context: new(gin.Context), + value: nil, + want: nil, + }, + { + context: new(gin.Context), + value: "foo", + want: nil, + }, + } + + // run tests + for _, test := range tests { + if test.value != nil { + test.context.Set(key, test.value) + } + + got := FromGinContext(test.context) + + if !reflect.DeepEqual(got, test.want) { + t.Errorf("FromGinContext is %v, want %v", got, test.want) + } + } +} + +func TestExecutor_WithContext(t *testing.T) { + // setup types + _service, _ := New(&Setup{}) + + //nolint:staticcheck,revive // ignore using string with context value + want := context.WithValue(context.Background(), key, _service) + + // run test + got := WithContext(context.Background(), _service) + + if !reflect.DeepEqual(got, want) { + t.Errorf("WithContext is %v, want %v", got, want) + } +} + +func TestExecutor_WithGinContext(t *testing.T) { + // setup types + _service, _ := New(&Setup{}) + + want := new(gin.Context) + want.Set(key, _service) + + // run test + got := new(gin.Context) + WithGinContext(got, _service) + + if !reflect.DeepEqual(got, want) { + t.Errorf("WithGinContext is %v, want %v", got, want) + } +} diff --git a/storage/flags.go b/storage/flags.go new file mode 100644 index 000000000..6c1d780f8 --- /dev/null +++ b/storage/flags.go @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 + +package storage + +import ( + "github.com/urfave/cli/v2" +) + +var Flags = []cli.Flag{ + // STORAGE Flags + + &cli.BoolFlag{ + EnvVars: []string{"VELA_STORAGE_ENABLE"}, + Name: "storage.enable", + Usage: "enable object storage", + }, + &cli.StringFlag{ + EnvVars: []string{"VELA_STORAGE_DRIVER"}, + Name: "storage.driver.name", + Usage: "object storage driver", + }, + &cli.StringFlag{ + EnvVars: []string{"VELA_STORAGE_ENDPOINT"}, + Name: "storage.endpoint.name", + Usage: "set the storage endpoint (ex. scheme://host:port)", + }, + + &cli.StringFlag{ + EnvVars: []string{"VELA_STORAGE_ACCESS_KEY"}, + Name: "storage.access.key", + Usage: "set storage access key", + }, + &cli.StringFlag{ + EnvVars: []string{"VELA_STORAGE_SECRET_KEY"}, + Name: "storage.secret.key", + Usage: "set storage secret key", + }, + &cli.StringFlag{ + EnvVars: []string{"VELA_STORAGE_BUCKET"}, + Name: "storage.bucket.name", + Usage: "set storage bucket name", + }, + &cli.BoolFlag{ + EnvVars: []string{"VELA_STORAGE_USE_SSL"}, + Name: "storage.use.ssl", + Usage: "enable storage to use SSL", + Value: true, + }, +} diff --git a/storage/minio/bucket_exists.go b/storage/minio/bucket_exists.go new file mode 100644 index 000000000..4a3704011 --- /dev/null +++ b/storage/minio/bucket_exists.go @@ -0,0 +1,16 @@ +package minio + +import ( + "context" +) + +// BucketExists checks if a bucket exists in MinIO. +func (c *MinioClient) BucketExists(ctx context.Context, bucketName string) (bool, error) { + c.Logger.Tracef("checking if bucket %s exists", bucketName) + + exists, err := c.client.BucketExists(ctx, bucketName) + if err != nil { + return false, err + } + return exists, nil +} diff --git a/storage/minio/create_bucket.go b/storage/minio/create_bucket.go new file mode 100644 index 000000000..4a6739986 --- /dev/null +++ b/storage/minio/create_bucket.go @@ -0,0 +1,25 @@ +package minio + +import ( + "context" + "github.com/minio/minio-go/v7" +) + +// CreateBucket creates a new bucket in MinIO. +func (c *MinioClient) CreateBucket(ctx context.Context, bucketName string, opts *minio.MakeBucketOptions) error { + c.Logger.Tracef("create new bucket: %s", bucketName) + if opts == nil { + opts = &minio.MakeBucketOptions{} + c.Logger.Trace("Using US Standard Region as location default") + } + err := c.client.MakeBucket(ctx, bucketName, *opts) + if err != nil { + exists, errBucketExists := c.BucketExists(ctx, bucketName) + if errBucketExists == nil && exists { + c.Logger.Tracef("Bucket %s already exists", bucketName) + return nil + } + return err + } + return nil +} diff --git a/storage/minio/delete_bucket.go b/storage/minio/delete_bucket.go new file mode 100644 index 000000000..cf06c2081 --- /dev/null +++ b/storage/minio/delete_bucket.go @@ -0,0 +1,14 @@ +package minio + +import "context" + +// DeleteBucket deletes a bucket in MinIO. +func (c *MinioClient) DeleteBucket(ctx context.Context, bucketName string) error { + c.Logger.Tracef("deleting bucketName: %s", bucketName) + + err := c.client.RemoveBucket(ctx, bucketName) + if err != nil { + return err + } + return nil +} diff --git a/storage/minio/doc.go b/storage/minio/doc.go new file mode 100644 index 000000000..c5576b1fd --- /dev/null +++ b/storage/minio/doc.go @@ -0,0 +1 @@ +package minio diff --git a/storage/minio/download.go b/storage/minio/download.go new file mode 100644 index 000000000..c176b34b4 --- /dev/null +++ b/storage/minio/download.go @@ -0,0 +1,16 @@ +package minio + +import ( + "context" + "github.com/minio/minio-go/v7" + "io" +) + +func (c *MinioClient) Download(ctx context.Context, bucketName, key string) ([]byte, error) { + object, err := c.client.GetObject(ctx, bucketName, key, minio.GetObjectOptions{}) + if err != nil { + return nil, err + } + defer object.Close() + return io.ReadAll(object) +} diff --git a/storage/minio/get_bucket_lifecycle.go b/storage/minio/get_bucket_lifecycle.go new file mode 100644 index 000000000..0153a3eb2 --- /dev/null +++ b/storage/minio/get_bucket_lifecycle.go @@ -0,0 +1,20 @@ +package minio + +import ( + "context" + "encoding/xml" +) + +// GetBucketLifecycle retrieves the lifecycle configuration for a bucket. +func (c *MinioClient) GetBucketLifecycle(ctx context.Context, bucketName string) (string, error) { + c.Logger.Tracef("getting lifecycle configuration for bucket %s", bucketName) + + lifecycleConfig, err := c.client.GetBucketLifecycle(ctx, bucketName) + if err != nil { + return "", err + } + + lifecycleBytes, err := xml.MarshalIndent(lifecycleConfig, "", " ") + + return string(lifecycleBytes), nil +} diff --git a/storage/minio/list_bucket.go b/storage/minio/list_bucket.go new file mode 100644 index 000000000..a619e7705 --- /dev/null +++ b/storage/minio/list_bucket.go @@ -0,0 +1,21 @@ +package minio + +import ( + "context" +) + +// ListBuckets lists all buckets in MinIO. +func (c *MinioClient) ListBuckets(ctx context.Context) ([]string, error) { + c.Logger.Trace("listing all buckets") + + buckets, err := c.client.ListBuckets(ctx) + if err != nil { + return nil, err + } + + bucketNames := make([]string, len(buckets)) + for i, bucket := range buckets { + bucketNames[i] = bucket.Name + } + return bucketNames, nil +} diff --git a/storage/minio/list_objects.go b/storage/minio/list_objects.go new file mode 100644 index 000000000..31d8b5b8f --- /dev/null +++ b/storage/minio/list_objects.go @@ -0,0 +1,23 @@ +package minio + +import ( + "context" + "github.com/minio/minio-go/v7" +) + +// ListObjects lists the objects in a bucket. +func (c *MinioClient) ListObjects(ctx context.Context, bucketName string) ([]string, error) { + c.Logger.Tracef("listing objects in bucket %s", bucketName) + + objectCh := c.client.ListObjects(ctx, bucketName, minio.ListObjectsOptions{}) + + var objects []string + for object := range objectCh { + if object.Err != nil { + return nil, object.Err + } + objects = append(objects, object.Key) + } + + return objects, nil +} diff --git a/storage/minio/minio.go b/storage/minio/minio.go new file mode 100644 index 000000000..983a548a2 --- /dev/null +++ b/storage/minio/minio.go @@ -0,0 +1,115 @@ +package minio + +import ( + "context" + "github.com/minio/minio-go/v7" + "github.com/sirupsen/logrus" + "time" +) + +// config holds the configuration for the MinIO client. +type config struct { + Endpoint string + AccessKey string + SecretKey string + Secure bool +} + +// MinioClient implements the Storage interface using MinIO. +type MinioClient struct { + config *config + client *minio.Client + Options *minio.Options + // https://pkg.go.dev/github.com/sirupsen/logrus#Entry + Logger *logrus.Entry +} + +// New creates a new MinIO client. +func New(endpoint string, opts ...ClientOpt) (*MinioClient, error) { + // create new Minio client + c := new(MinioClient) + + // create new fields + c.config = new(config) + c.Options = new(minio.Options) + + // create new logger for the client + logger := logrus.StandardLogger() + c.Logger = logrus.NewEntry(logger).WithField("storage", "minio") + + // apply all provided configuration options + for _, opt := range opts { + err := opt(c) + if err != nil { + return nil, err + } + } + + // create the Minio client from the provided endpoint and options + minioClient, err := minio.New(endpoint, c.Options) + if err != nil { + return nil, err + } + + c.client = minioClient + + return c, nil + //minioClient, err := minio.New(endpoint, &minio.Options{ + // Creds: credentials.NewStaticV4(accessKey, secretKey, ""), + // Secure: useSSL, + //}) + //if err != nil { + // return nil, err + //} + //return &MinioClient{client: minioClient}, nil +} + +// pingBucket checks if the specified bucket exists. +func pingBucket(c *MinioClient, bucket string) error { + for i := 0; i < 10; i++ { + _, err := c.client.BucketExists(context.Background(), bucket) + if err != nil { + c.Logger.Debugf("unable to ping %s. Retrying in %v", bucket, time.Duration(i)*time.Second) + time.Sleep(1 * time.Second) + + continue + } + } + + return nil +} + +//// UploadArtifact uploads an artifact to storage. +//func (c *MinioClient) UploadArtifact(ctx context.Context, workflowID, artifactName string, data []byte) error { +// key := path.Join("artifacts", workflowID, artifactName) +// bucket := "vela-artifacts" +// return c.upload(ctx, bucket, key, data) +//} +// +//// DownloadArtifact downloads an artifact from storage. +//func (c *MinioClient) DownloadArtifact(ctx context.Context, workflowID, artifactName string) ([]byte, error) { +// key := path.Join("artifacts", workflowID, artifactName) +// bucket := "vela-artifacts" +// return c.download(ctx, bucket, key) +//} +// +//// UploadCache uploads cache data to storage. +//func (c *MinioClient) UploadCache(ctx context.Context, key string, data []byte) error { +// cacheKey := path.Join("cache", key) +// bucket := "vela-cache" +// return c.upload(ctx, bucket, cacheKey, data) +//} +// +//// DownloadCache downloads cache data from storage. +//func (c *MinioClient) DownloadCache(ctx context.Context, key string) ([]byte, error) { +// cacheKey := path.Join("cache", key) +// bucket := "vela-cache" +// return c.download(ctx, bucket, cacheKey) +//} +// +//// DeleteCache deletes cache data from storage. +//func (c *MinioClient) DeleteCache(ctx context.Context, key string) error { +// cacheKey := path.Join("cache", key) +// bucket := "vela-cache" +// return c.client.RemoveObject(ctx, bucket, cacheKey, minio.RemoveObjectOptions{}) +//} diff --git a/storage/minio/opts.go b/storage/minio/opts.go new file mode 100644 index 000000000..a4ab86c5c --- /dev/null +++ b/storage/minio/opts.go @@ -0,0 +1,54 @@ +package minio + +import ( + "fmt" +) + +// ClientOpt represents a configuration option to initialize the MinIO client. +type ClientOpt func(client *MinioClient) error + +// WithAccessKey sets the access key in the MinIO client. +func WithAccessKey(accessKey string) ClientOpt { + return func(c *MinioClient) error { + c.Logger.Trace("configuring access key in minio client") + + // check if the access key provided is empty + if len(accessKey) == 0 { + return fmt.Errorf("no MinIO access key provided") + } + + // set the access key in the minio client + c.config.AccessKey = accessKey + + return nil + } +} + +// WithSecretKey sets the secret key in the MinIO client. +func WithSecretKey(secretKey string) ClientOpt { + return func(c *MinioClient) error { + c.Logger.Trace("configuring secret key in minio client") + + // check if the secret key provided is empty + if len(secretKey) == 0 { + return fmt.Errorf("no MinIO secret key provided") + } + + // set the secret key in the minio client + c.config.SecretKey = secretKey + + return nil + } +} + +// WithSecure sets the secure connection mode in the MinIO client. +func WithSecure(secure bool) ClientOpt { + return func(c *MinioClient) error { + c.Logger.Trace("configuring secure connection mode in minio client") + + // set the secure connection mode in the minio client + c.config.Secure = secure + + return nil + } +} diff --git a/storage/minio/set_bucket_lifecycle.go b/storage/minio/set_bucket_lifecycle.go new file mode 100644 index 000000000..8ea7a1993 --- /dev/null +++ b/storage/minio/set_bucket_lifecycle.go @@ -0,0 +1,20 @@ +package minio + +import ( + "context" + "encoding/xml" + "github.com/minio/minio-go/v7/pkg/lifecycle" +) + +// SetBucketLifecycle sets the lifecycle configuration for a bucket. +func (c *MinioClient) SetBucketLifecycle(ctx context.Context, bucketName string, lifecycleConfig string) error { + c.Logger.Tracef("setting lifecycle configuration for bucket %s", bucketName) + + var config lifecycle.Configuration + if err := xml.Unmarshal([]byte(lifecycleConfig), &config); err != nil { + c.Logger.Errorf("failed to unmarshal lifecycle configuration: %s", err) + return err + } + + return c.client.SetBucketLifecycle(ctx, bucketName, &config) +} diff --git a/storage/minio/upload.go b/storage/minio/upload.go new file mode 100644 index 000000000..10e50aaf1 --- /dev/null +++ b/storage/minio/upload.go @@ -0,0 +1,16 @@ +package minio + +import ( + "bytes" + "context" + "github.com/minio/minio-go/v7" +) + +// Helper methods for uploading objects +func (c *MinioClient) Upload(ctx context.Context, bucketName, objectName string, data []byte, contentType string) error { + c.Logger.Tracef("uploading data to bucket %s", bucketName) + + reader := bytes.NewReader(data) + _, err := c.client.PutObject(ctx, bucketName, objectName, reader, int64(len(data)), minio.PutObjectOptions{ContentType: contentType}) + return err +} diff --git a/storage/service.go b/storage/service.go new file mode 100644 index 000000000..552e66f08 --- /dev/null +++ b/storage/service.go @@ -0,0 +1,28 @@ +package storage + +import "context" + +// Storage defines the service interface for object storage operations. +type Storage interface { + // Bucket Management + CreateBucket(ctx context.Context, bucketName string) error + DeleteBucket(ctx context.Context, bucketName string) error + BucketExists(ctx context.Context, bucketName string) (bool, error) + ListBuckets(ctx context.Context) ([]string, error) + // Object Operations + Upload(ctx context.Context, bucketName string, objectName string, data []byte, contentType string) error + Download(ctx context.Context, bucketName string, objectName string) ([]byte, error) + Delete(ctx context.Context, bucketName string, objectName string) error + ListObjects(ctx context.Context, bucketName string, prefix string) ([]string, error) + //// Presigned URLs + //GeneratePresignedURL(ctx context.Context, bucket string, key string, expiry int64) (string, error) + // Object Lifecycle + SetBucketLifecycle(ctx context.Context, bucketName string, lifecycleConfig string) error + GetBucketLifecycle(ctx context.Context, bucketName string) (string, error) + //// Workflow-Specific Operations + //UploadArtifact(ctx context.Context, workflowID, artifactName string, data []byte) error + //DownloadArtifact(ctx context.Context, workflowID, artifactName string) ([]byte, error) + //UploadCache(ctx context.Context, key string, data []byte) error + //DownloadCache(ctx context.Context, key string) ([]byte, error) + //DeleteCache(ctx context.Context, key string) error +} diff --git a/storage/setup.go b/storage/setup.go new file mode 100644 index 000000000..f89354668 --- /dev/null +++ b/storage/setup.go @@ -0,0 +1,73 @@ +package storage + +import ( + "fmt" + "github.com/go-vela/server/storage/minio" + "github.com/sirupsen/logrus" +) + +// Setup represents the configuration necessary for +// creating a Vela service capable of integrating +// with a configured S3 environment. +type Setup struct { + Enable bool + Driver string + Endpoint string + AccessKey string + SecretKey string + Bucket string + Region string + Secure bool +} + +// Minio creates and returns a Vela service capable +// of integrating with an S3 environment. +func (s *Setup) Minio() (Storage, error) { + //client, err := minio.New(s.Endpoint, &minio.Options{ + // Creds: credentials.NewStaticV4(s.AccessKey, s.SecretKey, ""), + // Secure: s.Secure, + //}) + //if err != nil { + // return nil, err + //} + return minio.New( + s.Endpoint, + minio.WithAccessKey(s.AccessKey), + minio.WithSecretKey(s.SecretKey), + minio.WithSecure(s.Secure), + ) +} + +// Validate verifies the necessary fields for the +// provided configuration are populated correctly. +func (s *Setup) Validate() error { + logrus.Trace("validating Storage setup for client") + + // verify storage is enabled + if !s.Enable { + return fmt.Errorf("Storage is not enabled") + } + + // verify an endpoint was provided + if len(s.Endpoint) == 0 { + return fmt.Errorf("no storage endpoint provided") + } + + // verify an access key was provided + if len(s.AccessKey) == 0 { + return fmt.Errorf("no storage access key provided") + } + + // verify a secret key was provided + if len(s.SecretKey) == 0 { + return fmt.Errorf("no storage secret key provided") + } + + // verify a bucket was provided + if len(s.Bucket) == 0 { + return fmt.Errorf("no storage bucket provided") + } + + // setup is valid + return nil +} diff --git a/storage/storage.go b/storage/storage.go new file mode 100644 index 000000000..c2e9cf955 --- /dev/null +++ b/storage/storage.go @@ -0,0 +1,55 @@ +package storage + +import ( + "fmt" + "github.com/go-vela/server/constants" + "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" +) + +// FromCLIContext helper function to setup Minio Client from the CLI arguments. +func FromCLIContext(c *cli.Context) (Storage, error) { + logrus.Debug("creating Minio client from CLI configuration") + + // S3 configuration + _setup := &Setup{ + Enable: c.Bool("storage.enable"), + Driver: c.String("storage.driver.name"), + Endpoint: c.String("storage.endpoint.name"), + AccessKey: c.String("storage.access.key"), + SecretKey: c.String("storage.secret.key"), + Bucket: c.String("storage.bucket.name"), + Secure: c.Bool("storage.use.ssl"), + } + + return New(_setup) + +} + +// New creates and returns a Vela service capable of +// integrating with the configured storage environment. +// Currently, the following storages are supported: +// +// * minio +// . +func New(s *Setup) (Storage, error) { + // validate the setup being provided + // + err := s.Validate() + if err != nil { + return nil, err + } + logrus.Debug("creating storage client from setup") + // process the storage driver being provided + switch s.Driver { + case constants.DriverMinio: + // handle the Kafka queue driver being provided + // + // https://pkg.go.dev/github.com/go-vela/server/queue?tab=doc#Setup.Kafka + return s.Minio() + default: + // handle an invalid queue driver being provided + return nil, fmt.Errorf("invalid storage driver provided: %s", s.Driver) + } + +}