From 069f74259b650a71f1fce6ae0cdcdcf75879a93f Mon Sep 17 00:00:00 2001 From: Alex Collins Date: Tue, 15 Jun 2021 10:55:08 -0700 Subject: [PATCH] fix(executor): Capture emissary main-logs. Fixes #6145 (#6146) Signed-off-by: uturunku1 --- cmd/argoexec/commands/emissary.go | 2 +- test/e2e/artifacts_test.go | 12 ++++++ test/e2e/fixtures/e2e_suite.go | 5 +++ test/e2e/fixtures/given.go | 2 + test/e2e/fixtures/then.go | 63 ++++++++++++++++++++++++------- test/e2e/fixtures/when.go | 16 ++++---- 6 files changed, 79 insertions(+), 21 deletions(-) diff --git a/cmd/argoexec/commands/emissary.go b/cmd/argoexec/commands/emissary.go index db21a6f5df3a..446844834040 100644 --- a/cmd/argoexec/commands/emissary.go +++ b/cmd/argoexec/commands/emissary.go @@ -109,7 +109,7 @@ func NewEmissaryCommand() *cobra.Command { command.Stderr = os.Stderr // this may not be that important an optimisation, except for very long logs we don't want to capture - if includeScriptOutput { + if includeScriptOutput || template.SaveLogsAsArtifact() { logger.Info("capturing logs") stdout, err := os.Create(varRunArgo + "/ctr/" + containerName + "/stdout") if err != nil { diff --git a/test/e2e/artifacts_test.go b/test/e2e/artifacts_test.go index c3960a4bba1a..bb40b9980f3a 100644 --- a/test/e2e/artifacts_test.go +++ b/test/e2e/artifacts_test.go @@ -130,6 +130,18 @@ func (s *ArtifactsSuite) TestOutputResult() { }) } +func (s *ArtifactsSuite) TestMainLog() { + s.Given(). + Workflow("@testdata/basic-workflow.yaml"). + When(). + SubmitWorkflow(). + WaitForWorkflow(fixtures.ToBeSucceeded). + Then(). + ExpectArtifact("-", "main-logs", func(t *testing.T, data []byte) { + assert.NotEmpty(t, data) + }) +} + func TestArtifactsSuite(t *testing.T) { suite.Run(t, new(ArtifactsSuite)) } diff --git a/test/e2e/fixtures/e2e_suite.go b/test/e2e/fixtures/e2e_suite.go index 97e8c543d719..ca8a3125b8b5 100644 --- a/test/e2e/fixtures/e2e_suite.go +++ b/test/e2e/fixtures/e2e_suite.go @@ -207,6 +207,10 @@ func (s *E2ESuite) GetServiceAccountToken() (string, error) { } func (s *E2ESuite) Given() *Given { + bearerToken, err := s.GetServiceAccountToken() + if err != nil { + s.T().Fatal(err) + } return &Given{ t: s.T(), client: s.wfClient, @@ -216,5 +220,6 @@ func (s *E2ESuite) Given() *Given { cronClient: s.cronClient, hydrator: s.hydrator, kubeClient: s.KubeClient, + bearerToken: bearerToken, } } diff --git a/test/e2e/fixtures/given.go b/test/e2e/fixtures/given.go index 5ba510c677af..c2d00e942482 100644 --- a/test/e2e/fixtures/given.go +++ b/test/e2e/fixtures/given.go @@ -31,6 +31,7 @@ type Given struct { cwfTemplates []*wfv1.ClusterWorkflowTemplate cronWf *wfv1.CronWorkflow kubeClient kubernetes.Interface + bearerToken string } // creates a workflow based on the parameter, this may be: @@ -202,5 +203,6 @@ func (g *Given) When() *When { cronClient: g.cronClient, hydrator: g.hydrator, kubeClient: g.kubeClient, + bearerToken: g.bearerToken, } } diff --git a/test/e2e/fixtures/then.go b/test/e2e/fixtures/then.go index ddeec6b85953..b2a40c848e8d 100644 --- a/test/e2e/fixtures/then.go +++ b/test/e2e/fixtures/then.go @@ -3,6 +3,8 @@ package fixtures import ( "context" "fmt" + "io/ioutil" + "net/http" "reflect" "testing" "time" @@ -19,13 +21,14 @@ import ( ) type Then struct { - t *testing.T - wf *wfv1.Workflow - cronWf *wfv1.CronWorkflow - client v1alpha1.WorkflowInterface - cronClient v1alpha1.CronWorkflowInterface - hydrator hydrator.Interface - kubeClient kubernetes.Interface + t *testing.T + wf *wfv1.Workflow + cronWf *wfv1.CronWorkflow + client v1alpha1.WorkflowInterface + cronClient v1alpha1.CronWorkflowInterface + hydrator hydrator.Interface + kubeClient kubernetes.Interface + bearerToken string } func (t *Then) ExpectWorkflow(block func(t *testing.T, metadata *metav1.ObjectMeta, status *wfv1.WorkflowStatus)) *Then { @@ -173,6 +176,39 @@ func (t *Then) ExpectAuditEvents(filter func(event apiv1.Event) bool, num int, b return t } +func (t *Then) ExpectArtifact(nodeName, artifactName string, f func(t *testing.T, data []byte)) { + t.t.Helper() + nodeId := nodeIdForName(nodeName, t.wf) + url := "http://localhost:2746/artifacts/" + Namespace + "/" + t.wf.Name + "/" + nodeId + "/" + artifactName + println(url) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + t.t.Fatal(err) + } + req.Header.Set("Authorization", "Bearer "+t.bearerToken) + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.t.Fatal(err) + } + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.t.Fatal(err) + } + if resp.StatusCode != 200 { + t.t.Fatal(fmt.Errorf("HTTP request not OK: %s: %q", resp.Status, data)) + } + f(t.t, data) +} + +func nodeIdForName(nodeName string, wf *wfv1.Workflow) string { + if nodeName == "-" { + return wf.NodeID(wf.Name) + } else { + return wf.NodeID(nodeName) + } +} + func (t *Then) RunCli(args []string, block func(t *testing.T, output string, err error)) *Then { t.t.Helper() output, err := Exec("../../dist/argo", append([]string{"-n", Namespace}, args...)...) @@ -182,11 +218,12 @@ func (t *Then) RunCli(args []string, block func(t *testing.T, output string, err func (t *Then) When() *When { return &When{ - t: t.t, - client: t.client, - cronClient: t.cronClient, - hydrator: t.hydrator, - wf: t.wf, - kubeClient: t.kubeClient, + t: t.t, + client: t.client, + cronClient: t.cronClient, + hydrator: t.hydrator, + wf: t.wf, + kubeClient: t.kubeClient, + bearerToken: t.bearerToken, } } diff --git a/test/e2e/fixtures/when.go b/test/e2e/fixtures/when.go index 478b0a10b102..300c5192848a 100644 --- a/test/e2e/fixtures/when.go +++ b/test/e2e/fixtures/when.go @@ -33,6 +33,7 @@ type When struct { cronClient v1alpha1.CronWorkflowInterface hydrator hydrator.Interface kubeClient kubernetes.Interface + bearerToken string } func (w *When) SubmitWorkflow() *When { @@ -412,13 +413,14 @@ func (w *When) deleteResourceQuota(name string) *When { func (w *When) Then() *Then { return &Then{ - t: w.t, - wf: w.wf, - cronWf: w.cronWf, - client: w.client, - cronClient: w.cronClient, - hydrator: w.hydrator, - kubeClient: w.kubeClient, + t: w.t, + wf: w.wf, + cronWf: w.cronWf, + client: w.client, + cronClient: w.cronClient, + hydrator: w.hydrator, + kubeClient: w.kubeClient, + bearerToken: w.bearerToken, } }