Merge pull request #31200 from TerryHowe/fix-install-tests

fix: installer action goroutine count
pull/31198/merge
Scott Rigby 21 hours ago committed by GitHub
commit 50358d7ffd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -30,6 +30,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"text/template" "text/template"
"time" "time"
@ -129,6 +130,7 @@ type Install struct {
PostRenderer postrenderer.PostRenderer PostRenderer postrenderer.PostRenderer
// Lock to control raceconditions when the process receives a SIGTERM // Lock to control raceconditions when the process receives a SIGTERM
Lock sync.Mutex Lock sync.Mutex
goroutineCount atomic.Int32
} }
// ChartPathOptions captures common options used for controlling chart paths // ChartPathOptions captures common options used for controlling chart paths
@ -448,8 +450,10 @@ func (i *Install) performInstallCtx(ctx context.Context, rel *release.Release, t
resultChan := make(chan Msg, 1) resultChan := make(chan Msg, 1)
go func() { go func() {
i.goroutineCount.Add(1)
rel, err := i.performInstall(rel, toBeAdopted, resources) rel, err := i.performInstall(rel, toBeAdopted, resources)
resultChan <- Msg{rel, err} resultChan <- Msg{rel, err}
i.goroutineCount.Add(-1)
}() }()
select { select {
case <-ctx.Done(): case <-ctx.Done():
@ -460,6 +464,11 @@ func (i *Install) performInstallCtx(ctx context.Context, rel *release.Release, t
} }
} }
// getGoroutineCount return the number of running routines
func (i *Install) getGoroutineCount() int32 {
return i.goroutineCount.Load()
}
// isDryRun returns true if Upgrade is set to run as a DryRun // isDryRun returns true if Upgrade is set to run as a DryRun
func (i *Install) isDryRun() bool { func (i *Install) isDryRun() bool {
if i.DryRun || i.DryRunOption == "client" || i.DryRunOption == "server" || i.DryRunOption == "true" { if i.DryRun || i.DryRunOption == "client" || i.DryRunOption == "server" || i.DryRunOption == "true" {

@ -28,7 +28,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -329,8 +328,8 @@ func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
} }
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.Equal("with-notes", rel.Name)
is.NoError(err) is.NoError(err)
is.Equal("with-notes", rel.Name)
is.Equal("parent", rel.Info.Notes) is.Equal("parent", rel.Info.Notes)
is.Equal(rel.Info.Description, "Install complete") is.Equal(rel.Info.Description, "Install complete")
} }
@ -348,8 +347,8 @@ func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
} }
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.Equal("with-notes", rel.Name)
is.NoError(err) is.NoError(err)
is.Equal("with-notes", rel.Name)
// test run can return as either 'parent\nchild' or 'child\nparent' // test run can return as either 'parent\nchild' or 'child\nparent'
if !strings.Contains(rel.Info.Notes, "parent") && !strings.Contains(rel.Info.Notes, "child") { if !strings.Contains(rel.Info.Notes, "parent") && !strings.Contains(rel.Info.Notes, "child") {
t.Fatalf("Expected 'parent\nchild' or 'child\nparent', got '%s'", rel.Info.Notes) t.Fatalf("Expected 'parent\nchild' or 'child\nparent', got '%s'", rel.Info.Notes)
@ -453,9 +452,7 @@ func TestInstallReleaseIncorrectTemplate_DryRun(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Install should fail containing error: %s", expectedErr) t.Fatalf("Install should fail containing error: %s", expectedErr)
} }
if err != nil {
is.Contains(err.Error(), expectedErr) is.Contains(err.Error(), expectedErr)
}
} }
func TestInstallRelease_NoHooks(t *testing.T) { func TestInstallRelease_NoHooks(t *testing.T) {
@ -540,14 +537,14 @@ func TestInstallRelease_Wait(t *testing.T) {
instAction.WaitStrategy = kube.StatusWatcherStrategy instAction.WaitStrategy = kube.StatusWatcherStrategy
vals := map[string]interface{}{} vals := map[string]interface{}{}
goroutines := runtime.NumGoroutine() goroutines := instAction.getGoroutineCount()
res, err := instAction.Run(buildChart(), vals) res, err := instAction.Run(buildChart(), vals)
is.Error(err) is.Error(err)
is.Contains(res.Info.Description, "I timed out") is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(res.Info.Status, release.StatusFailed)
is.Equal(goroutines, runtime.NumGoroutine()) is.Equal(goroutines, instAction.getGoroutineCount())
} }
func TestInstallRelease_Wait_Interrupted(t *testing.T) { func TestInstallRelease_Wait_Interrupted(t *testing.T) {
is := assert.New(t) is := assert.New(t)
@ -562,15 +559,15 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context()) ctx, cancel := context.WithCancel(t.Context())
time.AfterFunc(time.Second, cancel) time.AfterFunc(time.Second, cancel)
goroutines := runtime.NumGoroutine() goroutines := instAction.getGoroutineCount()
_, err := instAction.RunWithContext(ctx, buildChart(), vals) _, err := instAction.RunWithContext(ctx, buildChart(), vals)
is.Error(err) is.Error(err)
is.Contains(err.Error(), "context canceled") is.Contains(err.Error(), "context canceled")
is.Equal(goroutines+1, runtime.NumGoroutine()) // installation goroutine still is in background is.Equal(goroutines+1, instAction.getGoroutineCount()) // installation goroutine still is in background
time.Sleep(10 * time.Second) // wait for goroutine to finish time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, runtime.NumGoroutine()) is.Equal(goroutines, instAction.getGoroutineCount())
} }
func TestInstallRelease_WaitForJobs(t *testing.T) { func TestInstallRelease_WaitForJobs(t *testing.T) {
is := assert.New(t) is := assert.New(t)
@ -646,7 +643,7 @@ func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context()) ctx, cancel := context.WithCancel(t.Context())
time.AfterFunc(time.Second, cancel) time.AfterFunc(time.Second, cancel)
goroutines := runtime.NumGoroutine() goroutines := instAction.getGoroutineCount()
res, err := instAction.RunWithContext(ctx, buildChart(), vals) res, err := instAction.RunWithContext(ctx, buildChart(), vals)
is.Error(err) is.Error(err)
@ -658,9 +655,9 @@ func TestInstallRelease_RollbackOnFailure_Interrupted(t *testing.T) {
_, err = instAction.cfg.Releases.Get(res.Name, res.Version) _, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err) is.Error(err)
is.Equal(err, driver.ErrReleaseNotFound) is.Equal(err, driver.ErrReleaseNotFound)
is.Equal(goroutines+1, runtime.NumGoroutine()) // installation goroutine still is in background is.Equal(goroutines+1, instAction.getGoroutineCount()) // installation goroutine still is in background
time.Sleep(10 * time.Second) // wait for goroutine to finish time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, runtime.NumGoroutine()) is.Equal(goroutines, instAction.getGoroutineCount())
} }
func TestNameTemplate(t *testing.T) { func TestNameTemplate(t *testing.T) {

Loading…
Cancel
Save