pull/32672/merge
Pujitha Paladugu 2 days ago committed by GitHub
commit 378cb57932
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -221,10 +221,21 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
if len(totalItems) > 0 {
var waiter kube.Waiter
var err error
// CRD establishment must always be awaited, regardless of the wait
// strategy configured for the release. HookOnlyStrategy's Wait is a
// no-op by design so that it can skip waiting for general chart
// resources, but skipping it here too lets Helm start creating
// custom resources before their CRDs are recognized by the API
// server. Use StatusWatcherStrategy for this check instead so CRDs
// are still waited for, matching Helm 3's unconditional behavior.
crdWaitStrategy := i.WaitStrategy
if crdWaitStrategy == kube.HookOnlyStrategy {
crdWaitStrategy = kube.StatusWatcherStrategy
}
if c, supportsOptions := i.cfg.KubeClient.(kube.InterfaceWaitOptions); supportsOptions {
waiter, err = c.GetWaiterWithOptions(i.WaitStrategy, i.WaitOptions...)
waiter, err = c.GetWaiterWithOptions(crdWaitStrategy, i.WaitOptions...)
} else {
waiter, err = i.cfg.KubeClient.GetWaiter(i.WaitStrategy)
waiter, err = i.cfg.KubeClient.GetWaiter(crdWaitStrategy)
}
if err != nil {
return fmt.Errorf("unable to get waiter: %w", err)

@ -1182,6 +1182,28 @@ func TestInstallCRDs_WaiterError(t *testing.T) {
require.Error(t, instAction.installCRDs(crdsToInstall), "wait error")
}
// TestInstallCRDs_HookOnlyStrategyStillWaitsForEstablishment guards against
// https://github.com/helm/helm/issues/32671: HookOnlyStrategy's waiter does not
// wait on general resources, so installCRDs() must request a
// StatusWatcherStrategy waiter for CRD establishment instead.
func TestInstallCRDs_HookOnlyStrategyStillWaitsForEstablishment(t *testing.T) {
config := actionConfigFixture(t)
failingKubeClient := kubefake.FailingKubeClient{PrintingKubeClient: kubefake.PrintingKubeClient{Out: io.Discard}, BuildDummy: true}
config.KubeClient = &failingKubeClient
instAction := NewInstall(config)
instAction.WaitStrategy = kube.HookOnlyStrategy
mockFile := common.File{
Name: "crds/foo.yaml",
Data: []byte("hello"),
}
mockChart := buildChart(withFile(mockFile))
crdsToInstall := mockChart.CRDObjects()
require.NoError(t, instAction.installCRDs(crdsToInstall))
assert.Equal(t, []kube.WaitStrategy{kube.StatusWatcherStrategy}, failingKubeClient.RecordedWaitStrategies)
}
func TestCheckDependencies(t *testing.T) {
dependency := chart.Dependency{Name: "hello"}
mockChart := buildChart(withDependency())

@ -50,6 +50,8 @@ type FailingKubeClient struct {
WaitDuration time.Duration
// RecordedWaitOptions stores the WaitOptions passed to GetWaiter for testing
RecordedWaitOptions []kube.WaitOption
// RecordedWaitStrategies stores the WaitStrategy passed to each GetWaiter call for testing
RecordedWaitStrategies []kube.WaitStrategy
mu sync.Mutex
}
@ -160,14 +162,15 @@ func (f *FailingKubeClient) GetWaiter(ws kube.WaitStrategy) (kube.Waiter, error)
return f.GetWaiterWithOptions(ws)
}
func (f *FailingKubeClient) appendRecordedWaitOptionsLocked(opts ...kube.WaitOption) {
func (f *FailingKubeClient) recordGetWaiterCallLocked(ws kube.WaitStrategy, opts ...kube.WaitOption) {
f.mu.Lock()
defer f.mu.Unlock()
f.RecordedWaitStrategies = append(f.RecordedWaitStrategies, ws)
f.RecordedWaitOptions = append(f.RecordedWaitOptions, opts...)
}
func (f *FailingKubeClient) GetWaiterWithOptions(ws kube.WaitStrategy, opts ...kube.WaitOption) (kube.Waiter, error) {
f.appendRecordedWaitOptionsLocked(opts...)
f.recordGetWaiterCallLocked(ws, opts...)
waiter, _ := f.PrintingKubeClient.GetWaiterWithOptions(ws, opts...)
printingKubeWaiter, _ := waiter.(*PrintingKubeWaiter)
return &FailingKubeWaiter{

Loading…
Cancel
Save