-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve e2e test flakyness #1825
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,12 @@ func TestDAGPipelineRun(t *testing.T) { | |
t.Fatalf("Failed to create echo Task: %s", err) | ||
} | ||
|
||
// Make sure the Pipeline has been created (wait for it) | ||
if err := WaitForTaskCreated(c, "echo-task", "TaskCreated"); err != nil { | ||
t.Errorf("Error waiting for Task echo-task to be created: %s", err) | ||
t.Fatal("Pipeline execution failed, Task echo-task has not been created") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Don't need a |
||
} | ||
|
||
// Create the repo PipelineResource (doesn't really matter which repo we use) | ||
repoResource := tb.PipelineResource("repo", namespace, tb.PipelineResourceSpec( | ||
v1alpha1.PipelineResourceTypeGit, | ||
|
@@ -105,6 +111,13 @@ func TestDAGPipelineRun(t *testing.T) { | |
if _, err := c.PipelineClient.Create(pipeline); err != nil { | ||
t.Fatalf("Failed to create dag-pipeline: %s", err) | ||
} | ||
|
||
// Make sure the Pipeline has been created (wait for it) | ||
if err := WaitForPipelineCreated(c, "dag-pipeline", "PipelineCreated"); err != nil { | ||
t.Errorf("Error waiting for Pipeline dag-pipeline to be created: %s", err) | ||
t.Fatal("Pipeline execution failed, Pipeline dag-pipeline has not been created") | ||
} | ||
|
||
pipelineRun := tb.PipelineRun("dag-pipeline-run", namespace, tb.PipelineRunSpec("dag-pipeline", | ||
tb.PipelineRunResourceBinding("repo", tb.PipelineResourceBindingRef("repo")), | ||
)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,36 @@ type TaskRunStateFn func(r *v1alpha1.TaskRun) (bool, error) | |
// PipelineRunStateFn is a condition function on TaskRun used polling functions | ||
type PipelineRunStateFn func(pr *v1alpha1.PipelineRun) (bool, error) | ||
|
||
// WaitForPipelineCreated wait until a pipeline has been created | ||
func WaitForPipelineCreated(c *clients, name, desc string) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice <3 |
||
metricName := fmt.Sprintf("WaitForPipelineCreated/%s/%s", name, desc) | ||
_, span := trace.StartSpan(context.Background(), metricName) | ||
defer span.End() | ||
|
||
return wait.PollImmediate(interval, timeout, func() (bool, error) { | ||
pc, err := c.PipelineClient.Get(name, metav1.GetOptions{}) | ||
if pc.GetName() == name { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why we need this check? Is it a way to check if no result was returned? |
||
return true, err | ||
} | ||
return false, nil | ||
}) | ||
} | ||
|
||
// WaitForTaskCreated wait until a task has been created | ||
func WaitForTaskCreated(c *clients, name, desc string) error { | ||
metricName := fmt.Sprintf("WaitForTaskCreated/%s/%s", name, desc) | ||
_, span := trace.StartSpan(context.Background(), metricName) | ||
defer span.End() | ||
|
||
return wait.PollImmediate(interval, timeout, func() (bool, error) { | ||
tc, err := c.TaskClient.Get(name, metav1.GetOptions{}) | ||
if tc.GetName() == name { | ||
return true, err | ||
} | ||
return false, err | ||
}) | ||
} | ||
|
||
// WaitForTaskRunState polls the status of the TaskRun called name from client every | ||
// interval until inState returns `true` indicating it is done, returns an | ||
// error or timeout. desc will be used to name the metric that is emitted to | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be worth adding a helper method to create-and-wait-for-existence a resource? I'm worried we'll forget to wait for existence every time we create a Task/Pipeline/etc., and have to chase flakes forever as a result.
Do we know why
Create
returns before the resource is actually reliably created? That seems like a problem for lots of tests. Is there somewhere we're using a lister in the reconciler to retrieve a Task/Pipeline, where we should be using a direct client to get them, bypassing caching? We've seen listers being slow to notice new objects in the past, and have (mostly?) replaced them with regular k8s clients as a result.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not so sure and more I read your comment and more I think that my patch may not address the fundamental problem, it doesn't matter if we know it has been created if it's actually the reconciler being slow to be notified.
I am not so sure about it (and probably will start to ping you about if i have to figure out :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pipeline/pkg/reconciler/pipelinerun/controller.go
Lines 72 to 82 in f1bfda6