Skip to content

Commit 7c8a655

Browse files
committed
pkg/apis: add scorecard v1alpha3 API
1 parent ffa71f1 commit 7c8a655

File tree

7 files changed

+409
-0
lines changed

7 files changed

+409
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/google/go-cmp v0.4.0 // indirect
1010
github.com/imdario/mergo v0.3.8 // indirect
1111
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
12+
github.com/mattn/go-isatty v0.0.8
1213
github.com/mikefarah/yq/v2 v2.4.1
1314
github.com/onsi/ginkgo v1.12.0 // indirect
1415
github.com/onsi/gomega v1.9.0 // indirect
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package v1alpha3
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
)
6+
7+
// ConfigurationKind is the default scorecard componentconfig kind.
8+
const ConfigurationKind = "Configuration"
9+
10+
// Configuration represents the set of test configurations which scorecard would run.
11+
type Configuration struct {
12+
metav1.TypeMeta `json:",inline" yaml:",inline"`
13+
14+
// Do not use metav1.ObjectMeta because this "object" should not be treated as an actual object.
15+
Metadata struct {
16+
// Name is a required field for kustomize-able manifests, and is not used on-cluster (nor is the config itself).
17+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
18+
} `json:"metadata,omitempty" yaml:"metadata,omitempty"`
19+
20+
// Stages is a set of test stages to run. Once a stage is finished, the next stage in the slice will be run.
21+
Stages []StageConfiguration `json:"stages" yaml:"stages"`
22+
}
23+
24+
// StageConfiguration configures a set of tests to be run.
25+
type StageConfiguration struct {
26+
// Parallel, if true, will run each test in tests in parallel.
27+
// The default is to wait until a test finishes to run the next.
28+
Parallel bool `json:"parallel,omitempty" yaml:"parallel,omitempty"`
29+
// Tests are a list of tests to run.
30+
Tests []TestConfiguration `json:"tests" yaml:"tests"`
31+
}
32+
33+
// TestConfiguration configures a specific scorecard test, identified by entrypoint.
34+
type TestConfiguration struct {
35+
// Image is the name of the test image.
36+
Image string `json:"image" yaml:"image"`
37+
// Entrypoint is a list of commands and arguments passed to the test image.
38+
Entrypoint []string `json:"entrypoint,omitempty" yaml:"entrypoint,omitempty"`
39+
// Labels further describe the test and enable selection.
40+
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
41+
}

pkg/apis/scorecard/v1alpha3/doc.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// +k8s:deepcopy-gen=package,register
2+
// +groupName=scorecard.operatorframework.io
3+
4+
// Package v1alpha3 contains resources types for version v1alpha3 of the scorecard.operatorframework.com API group.
5+
package v1alpha3
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package v1alpha3
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strings"
8+
9+
"github.com/mattn/go-isatty"
10+
)
11+
12+
const (
13+
redColor = "31"
14+
greenColor = "32"
15+
yellowColor = "33"
16+
noColor = "%s\n"
17+
)
18+
19+
func (s Test) MarshalText() string {
20+
var sb strings.Builder
21+
22+
failColor := "\033[1;" + redColor + "m%s\033[0m"
23+
passColor := "\033[1;" + greenColor + "m%s\033[0m"
24+
warnColor := "\033[1;" + yellowColor + "m%s\033[0m"
25+
26+
// turn off colorization if not in a terminal
27+
if !isatty.IsTerminal(os.Stdout.Fd()) &&
28+
!isatty.IsCygwinTerminal(os.Stdout.Fd()) {
29+
passColor = noColor
30+
failColor = noColor
31+
warnColor = noColor
32+
}
33+
34+
sb.WriteString(fmt.Sprintf("%s\n", strings.Repeat("-", 80)))
35+
sb.WriteString(fmt.Sprintf("Image: %s\n", s.Spec.Image))
36+
37+
if len(s.Spec.Entrypoint) > 0 {
38+
sb.WriteString(fmt.Sprintf("Entrypoint: %s\n", s.Spec.Entrypoint))
39+
}
40+
41+
if len(s.Spec.Labels) > 0 {
42+
sb.WriteString("Labels:\n")
43+
for labelKey, labelValue := range s.Spec.Labels {
44+
sb.WriteString(fmt.Sprintf("\t%q:%q\n", labelKey, labelValue))
45+
}
46+
}
47+
if len(s.Status.Results) > 0 {
48+
sb.WriteString("Results:\n")
49+
for _, result := range s.Status.Results {
50+
if len(result.Name) > 0 {
51+
sb.WriteString(fmt.Sprintf("\tName: %s\n", result.Name))
52+
}
53+
sb.WriteString("\tState: ")
54+
if result.State == PassState {
55+
sb.WriteString(fmt.Sprintf(passColor, PassState))
56+
} else if result.State == FailState {
57+
sb.WriteString(fmt.Sprintf(failColor, FailState))
58+
} else if result.State == ErrorState {
59+
sb.WriteString(fmt.Sprintf(failColor, ErrorState))
60+
} else {
61+
sb.WriteString("unknown")
62+
}
63+
sb.WriteString("\n")
64+
65+
if len(result.Suggestions) > 0 {
66+
sb.WriteString(fmt.Sprintf(warnColor, "\tSuggestions:\n"))
67+
for _, suggestion := range result.Suggestions {
68+
sb.WriteString(fmt.Sprintf("\t\t%s\n", suggestion))
69+
}
70+
}
71+
72+
if len(result.Errors) > 0 {
73+
sb.WriteString(fmt.Sprintf(failColor, "\tErrors:\n"))
74+
for _, err := range result.Errors {
75+
sb.WriteString(fmt.Sprintf("\t\t%s\n", err))
76+
}
77+
}
78+
79+
if result.Log != "" {
80+
sb.WriteString("\tLog:\n")
81+
scanner := bufio.NewScanner(strings.NewReader(result.Log))
82+
for scanner.Scan() {
83+
sb.WriteString(fmt.Sprintf("\t\t%s\n", scanner.Text()))
84+
}
85+
}
86+
sb.WriteString("\n")
87+
}
88+
}
89+
return sb.String()
90+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package v1alpha3
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/runtime/schema"
5+
"sigs.k8s.io/controller-runtime/pkg/scheme"
6+
)
7+
8+
var (
9+
// SchemeGroupVersion is group version used to register these objects
10+
SchemeGroupVersion = schema.GroupVersion{Group: "scorecard.operatorframework.io", Version: "v1alpha3"}
11+
12+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
13+
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
14+
)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package v1alpha3
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
)
6+
7+
// State is a type used to indicate the result state of a Test.
8+
type State string
9+
10+
const (
11+
// PassState occurs when a Test's ExpectedPoints == MaximumPoints.
12+
PassState State = "pass"
13+
// FailState occurs when a Test's ExpectedPoints == 0.
14+
FailState State = "fail"
15+
// ErrorState occurs when a Test encounters a fatal error and the reported points should not be considered.
16+
ErrorState State = "error"
17+
)
18+
19+
// TestResult contains the results of an individual scorecard test
20+
type TestResult struct {
21+
// Name is the name of the test
22+
Name string `json:"name,omitempty"`
23+
// Log holds a log produced from the test (if applicable)
24+
Log string `json:"log,omitempty"`
25+
// State is the final state of the test
26+
State State `json:"state"`
27+
// Errors is a list of the errors that occurred during the test (this can include both fatal and non-fatal errors)
28+
Errors []string `json:"errors,omitempty"`
29+
// Suggestions is a list of suggestions for the user to improve their score (if applicable)
30+
Suggestions []string `json:"suggestions,omitempty"`
31+
}
32+
33+
// TestStatus contains collection of testResults.
34+
type TestStatus struct {
35+
Results []TestResult `json:"results,omitempty"`
36+
}
37+
38+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
39+
40+
// Test specifies a single test run.
41+
type Test struct {
42+
metav1.TypeMeta `json:",inline"`
43+
Spec TestConfiguration `json:"spec,omitempty"`
44+
Status TestStatus `json:"status,omitempty"`
45+
}
46+
47+
// TestList is a list of tests.
48+
type TestList struct {
49+
metav1.TypeMeta `json:",inline"`
50+
Items []Test `json:"items"`
51+
}
52+
53+
func NewTest() Test {
54+
return Test{
55+
TypeMeta: metav1.TypeMeta{
56+
APIVersion: SchemeGroupVersion.String(),
57+
Kind: "Test",
58+
},
59+
}
60+
}
61+
62+
func NewTestList() TestList {
63+
return TestList{
64+
TypeMeta: metav1.TypeMeta{
65+
APIVersion: SchemeGroupVersion.String(),
66+
Kind: "TestList",
67+
},
68+
}
69+
}
70+
71+
func init() {
72+
SchemeBuilder.Register(&Test{})
73+
}

0 commit comments

Comments
 (0)