Skip to content

Commit

Permalink
Add context metadata for testruns when executed by the testrunner
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Schrodi authored and Tim Schrodi committed Mar 26, 2019
1 parent 84e41ad commit 890ee38
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 136 deletions.
10 changes: 5 additions & 5 deletions cmd/testrunner/cmd/runtemplate/run_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,23 +137,23 @@ var runCmd = &cobra.Command{
ComponentDescriptorPath: componenetDescriptorPath,
}

metadata := &result.Metadata{
metadata := &testrunner.Metadata{
Landscape: parameters.Landscape,
CloudProvider: parameters.Cloudprovider,
KubernetesVersion: parameters.K8sVersion,
}
testruns, err := testrunnerTemplate.Render(tmClient, parameters, metadata)
runs, err := testrunnerTemplate.Render(tmClient, parameters, metadata)
if err != nil {
log.Fatal(err)
}

finishedTestruns, err := testrunner.Run(config, testruns, testrunName)
failed, err := result.Collect(rsConfig, tmClient, config.Namespace, finishedTestruns, metadata)
finishedRuns, err := testrunner.ExecuteTestrun(config, runs, testrunName)
failed, err := result.Collect(rsConfig, tmClient, config.Namespace, finishedRuns)
if err != nil {
log.Fatal(err)
}

result.GenerateNotificationConfigForAlerting(finishedTestruns, rsConfig.ConcourseOnErrorDir)
result.GenerateNotificationConfigForAlerting(finishedRuns.GetTestruns(), rsConfig.ConcourseOnErrorDir)

log.Info("Testrunner finished.")
if failed {
Expand Down
14 changes: 10 additions & 4 deletions cmd/testrunner/cmd/runtestrun/run_testrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,24 @@ var runTestrunCmd = &cobra.Command{
log.Fatalf("Testrunner execution disrupted: %s", err.Error())
}

finishedTestruns, err := testrunner.Run(config, []*tmv1beta1.Testrun{&tr}, testrunNamePrefix)
run := []*testrunner.Run{
{
Testrun: &tr,
},
}

finishedRuns, err := testrunner.ExecuteTestrun(config, run, testrunNamePrefix)
if err != nil {
log.Fatalf("Testrunner execution disrupted: %s", err.Error())
}

if finishedTestruns[0].Status.Phase == tmv1beta1.PhaseStatusSuccess {
if finishedRuns[0].Testrun.Status.Phase == tmv1beta1.PhaseStatusSuccess {
log.Info("Testrunner successfully finished.")
} else {
log.Errorf("Testrunner finished with phase %s", finishedTestruns[0].Status.Phase)
log.Errorf("Testrunner finished with phase %s", finishedRuns[0].Testrun.Status.Phase)
}

fmt.Print(util.PrettyPrintStruct(finishedTestruns[0].Status))
fmt.Print(util.PrettyPrintStruct(finishedRuns[0].Testrun.Status))
},
}

Expand Down
18 changes: 10 additions & 8 deletions pkg/testrunner/result/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package result
import (
"fmt"

"github.com/gardener/test-infra/pkg/testrunner"

"github.com/gardener/gardener/pkg/client/kubernetes"
tmv1beta1 "github.com/gardener/test-infra/pkg/apis/testmachinery/v1beta1"
"github.com/gardener/test-infra/pkg/util"
Expand All @@ -25,10 +27,10 @@ import (

// Collect collects results of all testruns and write them to a file.
// It returns wheter there are failed testruns or not.
func Collect(config *Config, tmClient kubernetes.Interface, namespace string, testruns []*tmv1beta1.Testrun, metadata *Metadata) (bool, error) {
func Collect(config *Config, tmClient kubernetes.Interface, namespace string, runs testrunner.RunList) (bool, error) {
testrunsFailed := false
for _, tr := range testruns {
err := Output(config, tmClient, namespace, tr, metadata)
for _, run := range runs {
err := Output(config, tmClient, namespace, run.Testrun, run.Metadata)
if err != nil {
return false, err
}
Expand All @@ -37,19 +39,19 @@ func Collect(config *Config, tmClient kubernetes.Interface, namespace string, te
if err != nil {
log.Errorf("Cannot persist file %s: %s", config.OutputFile, err.Error())
} else {
err := MarkTestrunsAsIngested(tmClient, testruns)
err := MarkTestrunsAsIngested(tmClient, run.Testrun)
if err != nil {
log.Warn(err.Error())
}
}

if tr.Status.Phase == tmv1beta1.PhaseStatusSuccess {
log.Infof("Testrun %s finished successfully", tr.Name)
if run.Testrun.Status.Phase == tmv1beta1.PhaseStatusSuccess {
log.Infof("Testrun %s finished successfully", run.Testrun.Name)
} else {
testrunsFailed = true
log.Errorf("Testrun %s failed with phase %s", tr.Name, tr.Status.Phase)
log.Errorf("Testrun %s failed with phase %s", run.Testrun.Name, run.Testrun.Status.Phase)
}
fmt.Print(util.PrettyPrintStruct(tr.Status))
fmt.Print(util.PrettyPrintStruct(run.Testrun.Status))
}

return testrunsFailed, nil
Expand Down
17 changes: 8 additions & 9 deletions pkg/testrunner/result/ingest.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package result

import (
"context"
"fmt"
"os"
"os/exec"

Expand Down Expand Up @@ -46,18 +47,16 @@ func IngestFile(file, esCfgName string) error {
}

// MarkTestrunsAsIngested sets the ingest status of testruns to true
func MarkTestrunsAsIngested(tmClient kubernetes.Interface, testruns []*tmv1beta1.Testrun) error {
func MarkTestrunsAsIngested(tmClient kubernetes.Interface, tr *tmv1beta1.Testrun) error {
ctx := context.Background()
defer ctx.Done()
for _, tr := range testruns {
tr.Status.Ingested = true
err := tmClient.Client().Update(ctx, tr)
if err != nil {
log.Errorf("Cannot update status off testrun %s in namespace %s: %s", tr.Name, tr.Namespace, err.Error())
continue
}
log.Debugf("Successfully updated status of testrun %s in namespace %s", tr.Name, tr.Namespace)

tr.Status.Ingested = true
err := tmClient.Client().Update(ctx, tr)
if err != nil {
return fmt.Errorf("Cannot update status off testrun %s in namespace %s: %s", tr.Name, tr.Namespace, err.Error())
}
log.Debugf("Successfully updated status of testrun %s in namespace %s", tr.Name, tr.Namespace)

return nil
}
20 changes: 10 additions & 10 deletions pkg/testrunner/result/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"path"
"strings"

"github.com/gardener/test-infra/pkg/testrunner"

"github.com/gardener/test-infra/pkg/testmachinery"
"github.com/gardener/test-infra/pkg/testrunner/elasticsearch"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -40,13 +42,11 @@ import (
)

// Output takes a completed testrun status and writes the results to elastic search bulk json file.
func Output(config *Config, tmClient kubernetes.Interface, namespace string, tr *tmv1beta1.Testrun, metadata *Metadata) error {
func Output(config *Config, tmClient kubernetes.Interface, namespace string, tr *tmv1beta1.Testrun, metadata *testrunner.Metadata) error {
if config.OutputFile == "" {
return nil
}

metadata.TestrunID = tr.Name

if config.ArgoUIEndpoint != "" && tr.Status.Workflow != "" {
if u, err := url.ParseRequestURI(config.ArgoUIEndpoint); err == nil {
u.Path = path.Join(u.Path, "workflows", namespace, tr.Status.Workflow)
Expand Down Expand Up @@ -88,17 +88,17 @@ func Output(config *Config, tmClient kubernetes.Interface, namespace string, tr
return nil
}

func getTestrunSummary(tr *tmv1beta1.Testrun, metadata *Metadata) (*elasticsearch.Bulk, error) {
func getTestrunSummary(tr *tmv1beta1.Testrun, metadata *testrunner.Metadata) (*elasticsearch.Bulk, error) {

status := tr.Status
testsRun := 0
summaries := [][]byte{}

for _, steps := range status.Steps {
for _, step := range steps {
summary := StepSummary{
summary := testrunner.StepSummary{
Metadata: metadata,
Type: SummaryTypeTeststep,
Type: testrunner.SummaryTypeTeststep,
Name: step.TestDefinition.Name,
Phase: step.Phase,
StartTime: step.StartTime,
Expand All @@ -115,9 +115,9 @@ func getTestrunSummary(tr *tmv1beta1.Testrun, metadata *Metadata) (*elasticsearc
}
}

trSummary := TestrunSummary{
trSummary := testrunner.TestrunSummary{
Metadata: metadata,
Type: SummaryTypeTestrun,
Type: testrunner.SummaryTypeTestrun,
Phase: status.Phase,
StartTime: status.StartTime,
Duration: status.Duration,
Expand All @@ -135,7 +135,7 @@ func getTestrunSummary(tr *tmv1beta1.Testrun, metadata *Metadata) (*elasticsearc

}

func getExportedDocuments(cfg *testmachinery.ObjectStoreConfig, status tmv1beta1.TestrunStatus, metadata *Metadata) []byte {
func getExportedDocuments(cfg *testmachinery.ObjectStoreConfig, status tmv1beta1.TestrunStatus, metadata *testrunner.Metadata) []byte {

minioClient, err := minio.New(cfg.Endpoint, cfg.AccessKey, cfg.SecretKey, cfg.SSL)
if err != nil {
Expand All @@ -157,7 +157,7 @@ func getExportedDocuments(cfg *testmachinery.ObjectStoreConfig, status tmv1beta1
for _, steps := range status.Steps {
for _, step := range steps {
if step.Phase != argov1.NodeSkipped {
stepMeta := &StepExportMetadata{
stepMeta := &testrunner.StepExportMetadata{
Metadata: *metadata,
TestDefName: step.TestDefinition.Name,
Phase: step.Phase,
Expand Down
64 changes: 0 additions & 64 deletions pkg/testrunner/result/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@

package result

import (
argov1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
"github.com/gardener/test-infra/pkg/testrunner/componentdescriptor"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Config represents the configuration for collecting and storing results from a testrun.
type Config struct {
// OutputFilePath is the path where the testresult is written to.
Expand All @@ -41,64 +35,6 @@ type Config struct {
ConcourseOnErrorDir string
}

// SummaryType defines the type of a test result or summary
type SummaryType string

// Summary types can be testrun or teststep
const (
SummaryTypeTestrun SummaryType = "testrun"
SummaryTypeTeststep SummaryType = "teststep"
)

// Metadata is the common metadata of all ouputs and summaries.
type Metadata struct {
// Landscape describes the current dev,staging,canary,office or live.
Landscape string `json:"landscape"`
CloudProvider string `json:"cloudprovider"`
KubernetesVersion string `json:"k8s_version"`

// ComponentDescriptor describes the current component_descriptor of the direct landscape-setup components.
// It is formated as an array of components: { name: "my_component", version: "0.0.1" }
ComponentDescriptor []*componentdescriptor.Component `json:"bom"`

// Name of the testrun crd object.
TestrunID string `json:"testrun_id"`

// Link to the workflow in the argo ui
// Only set if an ingress with the name "argo-ui" for the argoui is set.
// Argo URL is in format: https://argo-endpoint.com/workflows/namespace/wf-name
ArgoUIExternalURL string `json:"argo_url"`
}

// StepExportMetadata is the metadata of one step of a testrun.
type StepExportMetadata struct {
Metadata
TestDefName string `json:"testdefinition"`
Phase argov1.NodePhase `json:"phase,omitempty"`
StartTime *metav1.Time `json:"startTime,omitempty"`
Duration int64 `json:"duration,omitempty"`
}

// TestrunSummary is the result of the overall testrun.
type TestrunSummary struct {
Metadata *Metadata `json:"tm"`
Type SummaryType `json:"type"`
Phase argov1.NodePhase `json:"phase,omitempty"`
StartTime *metav1.Time `json:"startTime,omitempty"`
Duration int64 `json:"duration,omitempty"`
TestsRun int `json:"testsRun,omitempty"`
}

// StepSummary is the result of a specific step.
type StepSummary struct {
Metadata *Metadata `json:"tm"`
Type SummaryType `json:"type"`
Name string `json:"name,omitempty"`
Phase argov1.NodePhase `json:"phase,omitempty"`
StartTime *metav1.Time `json:"startTime,omitempty"`
Duration int64 `json:"duration,omitempty"`
}

// notificationConfig is the configuration that is used by concourse to send notifications.
type notificationCfg struct {
Email email `yaml:"email"`
Expand Down
9 changes: 9 additions & 0 deletions pkg/testrunner/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
)

// GetTestruns returns all testruns of a RunList as testrun array
func (r RunList) GetTestruns() []*tmv1beta1.Testrun {
testruns := []*tmv1beta1.Testrun{}
for _, run := range r {
testruns = append(testruns, run.Testrun)
}
return testruns
}

func runTestrun(tmClient kubernetes.Interface, tr *tmv1beta1.Testrun, namespace, name string) (*tmv1beta1.Testrun, error) {
ctx := context.Background()
defer ctx.Done()
Expand Down
15 changes: 10 additions & 5 deletions pkg/testrunner/template/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

// RenderChart renders the provided helm chart with testruns, adds the testrun parameters and returns the templated files.
func RenderChart(tmClient kubernetes.Interface, parameters *TestrunParameters, versions []string) ([]string, error) {
func RenderChart(tmClient kubernetes.Interface, parameters *TestrunParameters, versions []string) ([]*TestrunFile, error) {
log.Debugf("Parameters: %+v", util.PrettyPrintStruct(parameters))
log.Debugf("Render chart from %s", parameters.TestrunChartPath)

Expand All @@ -25,7 +25,7 @@ func RenderChart(tmClient kubernetes.Interface, parameters *TestrunParameters, v
return nil, fmt.Errorf("Cannot read gardener kubeconfig %s, Error: %s", parameters.GardenKubeconfigPath, err.Error())
}

renderedFiles := []string{}
renderedFiles := []*TestrunFile{}
for _, version := range versions {
files, err := renderSingleChart(tmChartRenderer, parameters, gardenKubeconfig, version)
if err != nil {
Expand All @@ -36,7 +36,7 @@ func RenderChart(tmClient kubernetes.Interface, parameters *TestrunParameters, v
return renderedFiles, nil
}

func renderSingleChart(renderer chartrenderer.ChartRenderer, parameters *TestrunParameters, gardenKubeconfig []byte, version string) ([]string, error) {
func renderSingleChart(renderer chartrenderer.ChartRenderer, parameters *TestrunParameters, gardenKubeconfig []byte, version string) ([]*TestrunFile, error) {
chart, err := renderer.Render(parameters.TestrunChartPath, "", parameters.Namespace, map[string]interface{}{
"shoot": map[string]interface{}{
"name": fmt.Sprintf("%s-%s", parameters.ShootName, util.RandomString(5)),
Expand All @@ -61,9 +61,14 @@ func renderSingleChart(renderer chartrenderer.ChartRenderer, parameters *Testrun
return nil, err
}

files := []string{}
files := []*TestrunFile{}
for _, file := range chart.Files {
files = append(files, file)
files = append(files, &TestrunFile{
File: file,
Metadata: TestrunFileMetadata{
KubernetesVersion: version,
},
})
}

return files, nil
Expand Down
Loading

0 comments on commit 890ee38

Please sign in to comment.