@@ -13,6 +13,7 @@ import (
1313 "helm.sh/helm/v3/pkg/action"
1414 "helm.sh/helm/v3/pkg/chart"
1515 "helm.sh/helm/v3/pkg/release"
16+ "helm.sh/helm/v3/pkg/storage"
1617 "helm.sh/helm/v3/pkg/storage/driver"
1718 corev1 "k8s.io/api/core/v1"
1819 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -50,6 +51,7 @@ type mockActionGetter struct {
5051 reconcileErr error
5152 desiredRel * release.Release
5253 currentRel * release.Release
54+ config * action.Configuration
5355}
5456
5557func (mag * mockActionGetter ) ActionClientFor (ctx context.Context , obj client.Object ) (helmclient.ActionInterface , error ) {
@@ -98,6 +100,10 @@ func (mag *mockActionGetter) Reconcile(rel *release.Release) error {
98100 return mag .reconcileErr
99101}
100102
103+ func (mag * mockActionGetter ) Config () * action.Configuration {
104+ return mag .config
105+ }
106+
101107var (
102108 // required for unmockable call to convert.RegistryV1ToHelmChart
103109 validFS = fstest.MapFS {
@@ -179,6 +185,80 @@ func TestApply_Base(t *testing.T) {
179185 })
180186}
181187
188+ func TestApply_InterruptedRelease (t * testing.T ) {
189+ t .Run ("fails removing an interrupted install release" , func (t * testing.T ) {
190+ testRel := & release.Release {Name : "testrel" , Version : 0 , Info : & release.Info {Status : release .StatusPendingInstall }}
191+ testStorage := storage .Init (driver .NewMemory ())
192+
193+ mockAcg := & mockActionGetter {currentRel : testRel , config : & action.Configuration {Releases : testStorage }}
194+ helmApplier := applier.Helm {
195+ ActionClientGetter : mockAcg ,
196+ BundleToHelmChartFn : convert .RegistryV1ToHelmChart ,
197+ }
198+
199+ objs , state , err := helmApplier .Apply (context .TODO (), validFS , testCE , testObjectLabels , testStorageLabels )
200+ require .Error (t , err )
201+ require .ErrorContains (t , err , "removing interrupted release" )
202+ require .Nil (t , objs )
203+ require .Empty (t , state )
204+ })
205+
206+ t .Run ("fails removing an interrupted upgrade release" , func (t * testing.T ) {
207+ testRel := & release.Release {Name : "testrel" , Version : 0 , Info : & release.Info {Status : release .StatusPendingUpgrade }}
208+ testStorage := storage .Init (driver .NewMemory ())
209+
210+ mockAcg := & mockActionGetter {currentRel : testRel , config : & action.Configuration {Releases : testStorage }}
211+ helmApplier := applier.Helm {
212+ ActionClientGetter : mockAcg ,
213+ BundleToHelmChartFn : convert .RegistryV1ToHelmChart ,
214+ }
215+
216+ objs , state , err := helmApplier .Apply (context .TODO (), validFS , testCE , testObjectLabels , testStorageLabels )
217+ require .Error (t , err )
218+ require .ErrorContains (t , err , "removing interrupted release" )
219+ require .Nil (t , objs )
220+ require .Empty (t , state )
221+ })
222+
223+ t .Run ("successfully removes an interrupted install release" , func (t * testing.T ) {
224+ testRel := & release.Release {Name : "testrel" , Version : 0 , Info : & release.Info {Status : release .StatusPendingInstall }}
225+ testStorage := storage .Init (driver .NewMemory ())
226+ err := testStorage .Create (testRel )
227+ require .NoError (t , err )
228+
229+ mockAcg := & mockActionGetter {currentRel : testRel , config : & action.Configuration {Releases : testStorage }}
230+ helmApplier := applier.Helm {
231+ ActionClientGetter : mockAcg ,
232+ BundleToHelmChartFn : convert .RegistryV1ToHelmChart ,
233+ }
234+
235+ objs , state , err := helmApplier .Apply (context .TODO (), validFS , testCE , testObjectLabels , testStorageLabels )
236+ require .Error (t , err )
237+ require .ErrorContains (t , err , "removed interrupted release" )
238+ require .Nil (t , objs )
239+ require .Empty (t , state )
240+ })
241+
242+ t .Run ("successfully removes an interrupted upgrade release" , func (t * testing.T ) {
243+ testRel := & release.Release {Name : "testrel" , Version : 0 , Info : & release.Info {Status : release .StatusPendingUpgrade }}
244+ testStorage := storage .Init (driver .NewMemory ())
245+ err := testStorage .Create (testRel )
246+ require .NoError (t , err )
247+
248+ mockAcg := & mockActionGetter {currentRel : testRel , config : & action.Configuration {Releases : testStorage }}
249+ helmApplier := applier.Helm {
250+ ActionClientGetter : mockAcg ,
251+ BundleToHelmChartFn : convert .RegistryV1ToHelmChart ,
252+ }
253+
254+ objs , state , err := helmApplier .Apply (context .TODO (), validFS , testCE , testObjectLabels , testStorageLabels )
255+ require .Error (t , err )
256+ require .ErrorContains (t , err , "removed interrupted release" )
257+ require .Nil (t , objs )
258+ require .Empty (t , state )
259+ })
260+ }
261+
182262func TestApply_Installation (t * testing.T ) {
183263 t .Run ("fails during dry-run installation" , func (t * testing.T ) {
184264 mockAcg := & mockActionGetter {
@@ -340,6 +420,7 @@ func TestApply_Upgrade(t *testing.T) {
340420
341421 t .Run ("fails during dry-run upgrade" , func (t * testing.T ) {
342422 mockAcg := & mockActionGetter {
423+ currentRel : testCurrentRelease ,
343424 dryRunUpgradeErr : errors .New ("failed attempting to dry-run upgrade chart" ),
344425 }
345426 helmApplier := applier.Helm {
0 commit comments