Skip to content

Commit

Permalink
Wait for custom conditions on objects (kube-burner#308)
Browse files Browse the repository at this point in the history
* Allow waiting for conditions on custom resources

Add a waitOption key to the objects, to customize how to wait for
objects to be ready. Implement a forCondition option that allow to wait
for a condition to be true.

* Fix race condition when waiting for the iteration

Fix an issue where, if podwait was set to true, we could exit from our
waiters because listing the objects could initially return an empty
list.

* Update create.go

* Update create.go

* Update pkg/burner/create.go

---------

Co-authored-by: Raúl Sevilla <[email protected]>
  • Loading branch information
fcanovai and rsevilla87 authored May 12, 2023
1 parent 57685c1 commit 5c495d5
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 28 deletions.
12 changes: 11 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,18 @@ Each object element supports the following parameters:
| inputVars | Map of arbitrary input variables to inject to the object template | Object | - | - |
| namespaced | Whether to create a namespaced object or not | Boolean | false | true |
| wait | Wait for object to be ready[^1] | Boolean | false | true |
| waitOptions | Customize how to wait for object to be ready | Object | - | - |

[^1]: Kube-burner is only able to wait for a subset of resources. These resources are available in the `pkg/burner/waiters.go` file
[^1]: Kube-burner is only able to wait for a subset of resources, unless `waitOptions` are specified.
These resources are available in the `pkg/burner/waiters.go` file

### Wait Options

If you want to override the default waiter behaviors, you can specify wait options for your objects.

| Option | Description | Type | Example | Default |
|--------------|---------------------------------------------------------|---------|-------------|---------|
| forCondition | Wait for the object condition with this name to be true | String | myCondition | - |

### Default labels

Expand Down
2 changes: 2 additions & 0 deletions pkg/burner/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func setupCreateJob(jobConfig config.Job) Executor {
inputVars: o.InputVars,
namespaced: o.Namespaced,
wait: o.Wait,
waitOptions: o.WaitOptions,
}
// If any of the objects is namespaced, we configure the job to create namepaces
if o.Namespaced {
Expand Down Expand Up @@ -141,6 +142,7 @@ func (ex *Executor) RunCreateJob(iterationStart, iterationEnd int) {
if ex.Config.PodWait {
if !ex.Config.NamespacedIterations || !namespacesWaited[ns] {
log.Infof("Waiting up to %s for actions to be completed in namespace %s", ex.Config.MaxWaitTimeout, ns)
wg.Wait()
ex.waitForObjects(ns)
namespacesWaited[ns] = true
}
Expand Down
1 change: 1 addition & 0 deletions pkg/burner/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type object struct {
namespaced bool
kind string
wait bool
waitOptions config.WaitOptions
}

// Executor contains the information required to execute a job
Expand Down
64 changes: 37 additions & 27 deletions pkg/burner/waiters.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,37 @@ func (ex *Executor) waitForObjects(ns string) {
for _, obj := range ex.objects {
if obj.wait {
wg.Add(1)
switch obj.kind {
case "Deployment":
go waitForDeployments(ns, ex.Config.MaxWaitTimeout, &wg)
case "ReplicaSet":
go waitForRS(ns, ex.Config.MaxWaitTimeout, &wg)
case "ReplicationController":
go waitForRC(ns, ex.Config.MaxWaitTimeout, &wg)
case "StatefulSet":
go waitForStatefulSet(ns, ex.Config.MaxWaitTimeout, &wg)
case "DaemonSet":
go waitForDS(ns, ex.Config.MaxWaitTimeout, &wg)
case "Pod":
go waitForPod(ns, ex.Config.MaxWaitTimeout, &wg)
case "Build", "BuildConfig":
go waitForBuild(ns, ex.Config.MaxWaitTimeout, obj.replicas, &wg)
case "VirtualMachine":
go waitForVM(ns, ex.Config.MaxWaitTimeout, &wg)
case "VirtualMachineInstance":
go waitForVMI(ns, ex.Config.MaxWaitTimeout, &wg)
case "VirtualMachineInstanceReplicaSet":
go waitForVMIRS(ns, ex.Config.MaxWaitTimeout, &wg)
case "Job":
go waitForJob(ns, ex.Config.MaxWaitTimeout, &wg)
case "PersistentVolumeClaim":
go waitForPVC(ns, ex.Config.MaxWaitTimeout, &wg)
default:
wg.Done()
if obj.waitOptions.ForCondition != "" {
go waitForCondition(obj.gvr, ns, obj.waitOptions.ForCondition, ex.Config.MaxWaitTimeout, &wg)
} else {
switch obj.kind {
case "Deployment":
go waitForDeployments(ns, ex.Config.MaxWaitTimeout, &wg)
case "ReplicaSet":
go waitForRS(ns, ex.Config.MaxWaitTimeout, &wg)
case "ReplicationController":
go waitForRC(ns, ex.Config.MaxWaitTimeout, &wg)
case "StatefulSet":
go waitForStatefulSet(ns, ex.Config.MaxWaitTimeout, &wg)
case "DaemonSet":
go waitForDS(ns, ex.Config.MaxWaitTimeout, &wg)
case "Pod":
go waitForPod(ns, ex.Config.MaxWaitTimeout, &wg)
case "Build", "BuildConfig":
go waitForBuild(ns, ex.Config.MaxWaitTimeout, obj.replicas, &wg)
case "VirtualMachine":
go waitForVM(ns, ex.Config.MaxWaitTimeout, &wg)
case "VirtualMachineInstance":
go waitForVMI(ns, ex.Config.MaxWaitTimeout, &wg)
case "VirtualMachineInstanceReplicaSet":
go waitForVMIRS(ns, ex.Config.MaxWaitTimeout, &wg)
case "Job":
go waitForJob(ns, ex.Config.MaxWaitTimeout, &wg)
case "PersistentVolumeClaim":
go waitForPVC(ns, ex.Config.MaxWaitTimeout, &wg)
default:
wg.Done()
}
}
}
}
Expand Down Expand Up @@ -221,6 +225,12 @@ func waitForJob(ns string, maxWaitTimeout time.Duration, wg *sync.WaitGroup) {
verifyCondition(gvr, ns, "Complete", maxWaitTimeout)
}

func waitForCondition(gvr schema.GroupVersionResource, ns, condition string, maxWaitTimeout time.Duration,
wg *sync.WaitGroup) {
defer wg.Done()
verifyCondition(gvr, ns, condition, maxWaitTimeout)
}

func verifyCondition(gvr schema.GroupVersionResource, ns, condition string, maxWaitTimeout time.Duration) {
var uObj types.UnstructuredContent
wait.PollUntilContextTimeout(context.TODO(), 10*time.Second, maxWaitTimeout, true, func(ctx context.Context) (done bool, err error) {
Expand Down
7 changes: 7 additions & 0 deletions pkg/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ type Object struct {
Namespaced bool `yaml:"namespaced" json:"namespaced"`
// Wait for resource to be ready, it doesn't apply to all resources
Wait bool `yaml:"wait" json:"wait"`
// WaitOptions define custom behaviors when waiting for objects creation
WaitOptions WaitOptions `yaml:"waitOptions" json:"waitOptions,omitempty"`
}

// Job defines a kube-burner job
Expand Down Expand Up @@ -140,3 +142,8 @@ type Job struct {
// Churn delay between sets
ChurnDelay time.Duration `yaml:"churnDelay" json:"churnDelay,omitempty"`
}

type WaitOptions struct {
// ForCondition wait for this condition to become true
ForCondition string `yaml:"forCondition" json:"forCondition,omitempty"`
}

0 comments on commit 5c495d5

Please sign in to comment.