@@ -108,7 +108,7 @@ type ReleasePlanInstallOptions struct {
108108}
109109
110110// Plans the next release installation without applying changes to the cluster.
111- func ReleasePlanInstall (ctx context.Context , releaseName , releaseNamespace string , opts ReleasePlanInstallOptions ) error {
111+ func ReleasePlanInstall (ctx context.Context , releaseName , releaseNamespace string , opts ReleasePlanInstallOptions ) ( * plan. Artifact , error ) {
112112 ctx , ctxCancelFn := context .WithCancelCause (ctx )
113113
114114 if opts .Timeout == 0 {
@@ -118,35 +118,41 @@ func ReleasePlanInstall(ctx context.Context, releaseName, releaseNamespace strin
118118 ctx , _ = context .WithTimeoutCause (ctx , opts .Timeout , fmt .Errorf ("context timed out: action timed out after %s" , opts .Timeout .String ()))
119119 defer ctxCancelFn (fmt .Errorf ("context canceled: action finished" ))
120120
121- actionCh := make (chan error , 1 )
121+ type actionResult struct {
122+ artifact * plan.Artifact // Replace with your actual type
123+ err error
124+ }
125+
126+ actionCh := make (chan actionResult , 1 )
122127 go func () {
123- actionCh <- releasePlanInstall (ctx , ctxCancelFn , releaseName , releaseNamespace , opts )
128+ planArtifact , err := releasePlanInstall (ctx , ctxCancelFn , releaseName , releaseNamespace , opts )
129+ actionCh <- actionResult {artifact : planArtifact , err : err }
124130 }()
125131
126132 for {
127133 select {
128- case err := <- actionCh :
129- return err
134+ case res := <- actionCh :
135+ return res . artifact , res . err
130136 case <- ctx .Done ():
131- return context .Cause (ctx )
137+ return nil , context .Cause (ctx )
132138 }
133139 }
134140}
135141
136- func releasePlanInstall (ctx context.Context , ctxCancelFn context.CancelCauseFunc , releaseName , releaseNamespace string , opts ReleasePlanInstallOptions ) error {
142+ func releasePlanInstall (ctx context.Context , ctxCancelFn context.CancelCauseFunc , releaseName , releaseNamespace string , opts ReleasePlanInstallOptions ) ( * plan. Artifact , error ) {
137143 currentDir , err := os .Getwd ()
138144 if err != nil {
139- return fmt .Errorf ("get current working directory: %w" , err )
145+ return nil , fmt .Errorf ("get current working directory: %w" , err )
140146 }
141147
142148 homeDir , err := os .UserHomeDir ()
143149 if err != nil {
144- return fmt .Errorf ("get home directory: %w" , err )
150+ return nil , fmt .Errorf ("get home directory: %w" , err )
145151 }
146152
147153 opts , err = applyReleasePlanInstallOptionsDefaults (opts , currentDir , homeDir )
148154 if err != nil {
149- return fmt .Errorf ("build release plan install options: %w" , err )
155+ return nil , fmt .Errorf ("build release plan install options: %w" , err )
150156 }
151157
152158 if opts .SecretKey != "" {
@@ -158,12 +164,12 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
158164 KubeContextNamespace : releaseNamespace , // TODO: unset it everywhere
159165 })
160166 if err != nil {
161- return fmt .Errorf ("construct kube config: %w" , err )
167+ return nil , fmt .Errorf ("construct kube config: %w" , err )
162168 }
163169
164170 clientFactory , err := kube .NewClientFactory (ctx , kubeConfig )
165171 if err != nil {
166- return fmt .Errorf ("construct kube client factory: %w" , err )
172+ return nil , fmt .Errorf ("construct kube client factory: %w" , err )
167173 }
168174
169175 helmRegistryClientOpts := []registry.ClientOption {
@@ -181,14 +187,14 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
181187
182188 helmRegistryClient , err := registry .NewClient (helmRegistryClientOpts ... )
183189 if err != nil {
184- return fmt .Errorf ("construct registry client: %w" , err )
190+ return nil , fmt .Errorf ("construct registry client: %w" , err )
185191 }
186192
187193 releaseStorage , err := release .NewReleaseStorage (ctx , releaseNamespace , opts .ReleaseStorageDriver , clientFactory , release.ReleaseStorageOptions {
188194 SQLConnection : opts .ReleaseStorageSQLConnection ,
189195 })
190196 if err != nil {
191- return fmt .Errorf ("construct release storage: %w" , err )
197+ return nil , fmt .Errorf ("construct release storage: %w" , err )
192198 }
193199
194200 helmOptions := common.HelmOptions {
@@ -213,7 +219,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
213219
214220 history , err := release .BuildHistory (releaseName , releaseStorage , release.HistoryOptions {})
215221 if err != nil {
216- return fmt .Errorf ("build release history: %w" , err )
222+ return nil , fmt .Errorf ("build release history: %w" , err )
217223 }
218224
219225 releases := history .Releases ()
@@ -257,7 +263,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
257263 TemplatesAllowDNS : opts .TemplatesAllowDNS ,
258264 })
259265 if err != nil {
260- return fmt .Errorf ("render chart: %w" , err )
266+ return nil , fmt .Errorf ("render chart: %w" , err )
261267 }
262268
263269 log .Default .Debug (ctx , "Build transformed resource specs" )
@@ -267,7 +273,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
267273 spec .NewDropInvalidAnnotationsAndLabelsTransformer (),
268274 })
269275 if err != nil {
270- return fmt .Errorf ("build transformed resource specs: %w" , err )
276+ return nil , fmt .Errorf ("build transformed resource specs: %w" , err )
271277 }
272278
273279 log .Default .Debug (ctx , "Build releasable resource specs" )
@@ -283,7 +289,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
283289
284290 releasableResSpecs , err := spec .BuildReleasableResourceSpecs (ctx , releaseNamespace , transformedResSpecs , patchers )
285291 if err != nil {
286- return fmt .Errorf ("build releasable resource specs: %w" , err )
292+ return nil , fmt .Errorf ("build releasable resource specs: %w" , err )
287293 }
288294
289295 newRelease , err := release .NewRelease (releaseName , releaseNamespace , newRevision , deployType , releasableResSpecs , renderChartResult .Chart , renderChartResult .ReleaseConfig , release.ReleaseOptions {
@@ -292,7 +298,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
292298 Notes : renderChartResult .Notes ,
293299 })
294300 if err != nil {
295- return fmt .Errorf ("construct new release: %w" , err )
301+ return nil , fmt .Errorf ("construct new release: %w" , err )
296302 }
297303
298304 log .Default .Debug (ctx , "Convert previous release to resource specs" )
@@ -301,15 +307,15 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
301307 if prevRelease != nil {
302308 prevRelResSpecs , err = release .ReleaseToResourceSpecs (prevRelease , releaseNamespace , false )
303309 if err != nil {
304- return fmt .Errorf ("convert previous release to resource specs: %w" , err )
310+ return nil , fmt .Errorf ("convert previous release to resource specs: %w" , err )
305311 }
306312 }
307313
308314 log .Default .Debug (ctx , "Convert new release to resource specs" )
309315
310316 newRelResSpecs , err := release .ReleaseToResourceSpecs (newRelease , releaseNamespace , false )
311317 if err != nil {
312- return fmt .Errorf ("convert new release to resource specs: %w" , err )
318+ return nil , fmt .Errorf ("convert new release to resource specs: %w" , err )
313319 }
314320
315321 log .Default .Debug (ctx , "Build resources" )
@@ -322,13 +328,13 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
322328 DefaultDeletePropagation : metav1 .DeletionPropagation (opts .DefaultDeletePropagation ),
323329 })
324330 if err != nil {
325- return fmt .Errorf ("build resources: %w" , err )
331+ return nil , fmt .Errorf ("build resources: %w" , err )
326332 }
327333
328334 log .Default .Debug (ctx , "Locally validate resources" )
329335
330336 if err := resource .ValidateLocal (ctx , releaseNamespace , instResources , opts .ResourceValidationOptions ); err != nil {
331- return fmt .Errorf ("locally validate resources: %w" , err )
337+ return nil , fmt .Errorf ("locally validate resources: %w" , err )
332338 }
333339
334340 log .Default .Debug (ctx , "Build resource infos" )
@@ -339,7 +345,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
339345 if lastDeployedOrLastRelease != nil {
340346 lastDeployedOrLastRelResSpecs , err = release .ReleaseToResourceSpecs (lastDeployedOrLastRelease , releaseNamespace , false )
341347 if err != nil {
342- return fmt .Errorf ("convert last deployed or last release to resource specs: %w" , err )
348+ return nil , fmt .Errorf ("convert last deployed or last release to resource specs: %w" , err )
343349 }
344350 }
345351
@@ -349,20 +355,20 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
349355 LastDeployedOrLastRelResourceSpecs : lastDeployedOrLastRelResSpecs ,
350356 })
351357 if err != nil {
352- return fmt .Errorf ("build resource infos: %w" , err )
358+ return nil , fmt .Errorf ("build resource infos: %w" , err )
353359 }
354360
355361 log .Default .Debug (ctx , "Remotely validate resources" )
356362
357363 if err := plan .ValidateRemote (releaseName , releaseNamespace , instResInfos , opts .ForceAdoption ); err != nil {
358- return fmt .Errorf ("remotely validate resources: %w" , err )
364+ return nil , fmt .Errorf ("remotely validate resources: %w" , err )
359365 }
360366
361367 log .Default .Debug (ctx , "Build release infos" )
362368
363369 relInfos , err := plan .BuildReleaseInfos (ctx , deployType , releases , newRelease )
364370 if err != nil {
365- return fmt .Errorf ("build release infos: %w" , err )
371+ return nil , fmt .Errorf ("build release infos: %w" , err )
366372 }
367373
368374 log .Default .Debug (ctx , "Build install plan" )
@@ -373,18 +379,18 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
373379 if err != nil {
374380 handleBuildPlanErr (ctx , installPlan , err , opts .InstallGraphPath , opts .TempDirPath , "release-install-graph.dot" )
375381
376- return fmt .Errorf ("build install plan: %w" , err )
382+ return nil , fmt .Errorf ("build install plan: %w" , err )
377383 }
378384
379385 if opts .InstallGraphPath != "" {
380386 if err := savePlanAsDot (installPlan , opts .InstallGraphPath ); err != nil {
381- return fmt .Errorf ("save release install graph: %w" , err )
387+ return nil , fmt .Errorf ("save release install graph: %w" , err )
382388 }
383389 }
384390
385391 releaseIsUpToDate , err := release .IsReleaseUpToDate (prevRelease , newRelease )
386392 if err != nil {
387- return fmt .Errorf ("check if release is up to date: %w" , err )
393+ return nil , fmt .Errorf ("check if release is up to date: %w" , err )
388394 }
389395
390396 installPlanIsUseless := lo .NoneBy (installPlan .Operations (), func (op * plan.Operation ) bool {
@@ -400,7 +406,7 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
400406
401407 changes , err := plan .CalculatePlannedChanges (instResInfos , delResInfos )
402408 if err != nil {
403- return fmt .Errorf ("calculate planned changes: %w" , err )
409+ return nil , fmt .Errorf ("calculate planned changes: %w" , err )
404410 }
405411
406412 if releaseIsUpToDate && installPlanIsUseless {
@@ -409,56 +415,56 @@ func releasePlanInstall(ctx context.Context, ctxCancelFn context.CancelCauseFunc
409415 log .Default .Info (ctx , color.Style {color .Bold , color .Yellow }.Render (fmt .Sprintf ("No resource changes planned, but still must install release %q (namespace: %q)" , releaseName , releaseNamespace )))
410416 }
411417
412- if err := logPlannedChanges (ctx , releaseName , releaseNamespace , changes , opts .ResourceDiffOptions ); err != nil {
413- return fmt .Errorf ("log planned changes: %w" , err )
418+ planArtifact := & plan.Artifact {
419+ APIVersion : plan .ArtifactSchemeVersion ,
420+ Data : & plan.ArtifactData {
421+ Options : opts .ReleaseInstallRuntimeOptions ,
422+ Release : newRelease ,
423+ Plan : installPlan ,
424+ Changes : changes ,
425+ InstallableResourceInfos : instResInfos ,
426+ ReleaseInfos : relInfos ,
427+ },
428+ DeployType : deployType ,
429+ Release : plan.ArtifactRelease {
430+ Name : releaseName ,
431+ Namespace : releaseNamespace ,
432+ Revision : newRelease .Version ,
433+ },
434+ Timestamp : time .Now ().UTC (),
414435 }
415436
416- if opts .PlanArtifactPath != "" {
417- planArtifact := & plan.PlanArtifact {
418- APIVersion : plan .PlanArtifactSchemeVersion ,
419- Data : & plan.PlanArtifactData {
420- Options : opts .ReleaseInstallRuntimeOptions ,
421- Release : newRelease ,
422- Plan : installPlan ,
423- Changes : changes ,
424- InstallableResourceInfos : instResInfos ,
425- ReleaseInfos : relInfos ,
426- },
427- DeployType : deployType ,
428- Release : plan.PlanArtifactRelease {
429- Name : releaseName ,
430- Namespace : releaseNamespace ,
431- Revision : newRelease .Version ,
432- },
433- Timestamp : time .Now ().UTC (),
434- }
437+ if err := logPlannedChanges (ctx , planArtifact , opts .ResourceDiffOptions ); err != nil {
438+ return nil , fmt .Errorf ("log planned changes: %w" , err )
439+ }
435440
436- if err := plan .WritePlanArtifact (ctx , planArtifact , opts .PlanArtifactPath , opts .SecretKey , opts .SecretWorkDir ); err != nil {
437- return fmt .Errorf ("save install plan to %q: %w" , opts .PlanArtifactPath , err )
441+ if opts .PlanArtifactPath != "" {
442+ if err := plan .WriteArtifact (ctx , planArtifact , opts .PlanArtifactPath , opts .SecretKey , opts .SecretWorkDir ); err != nil {
443+ return nil , fmt .Errorf ("save install plan to %q: %w" , opts .PlanArtifactPath , err )
438444 }
439445 }
440446
441447 if opts .ErrorIfChangesPlanned {
442448 if releaseIsUpToDate && installPlanIsUseless {
443- return nil
449+ return planArtifact , nil
444450 } else if installPlanIsUseless || len (changes ) == 0 {
445- return ErrReleaseInstallPlanned
451+ return planArtifact , ErrReleaseInstallPlanned
446452 }
447453
448- return ErrResourceChangesPlanned
454+ return planArtifact , ErrResourceChangesPlanned
449455 }
450456
451- return nil
457+ return planArtifact , nil
452458}
453459
454- func logPlannedChanges (ctx context.Context , releaseName , releaseNamespace string , changes [] * plan.ResourceChange , opts common.ResourceDiffOptions ) error {
455- if len (changes ) == 0 {
460+ func logPlannedChanges (ctx context.Context , planArtifact * plan.Artifact , opts common.ResourceDiffOptions ) error {
461+ if len (planArtifact . Data . Changes ) == 0 {
456462 return nil
457463 }
458464
459465 log .Default .Info (ctx , "" )
460466
461- for _ , change := range changes {
467+ for _ , change := range planArtifact . Data . Changes {
462468 if err := log .Default .InfoBlockErr (ctx , log.BlockOptions {
463469 BlockTitle : buildDiffHeader (change ),
464470 }, func () error {
@@ -479,10 +485,10 @@ func logPlannedChanges(ctx context.Context, releaseName, releaseNamespace string
479485 }
480486 }
481487
482- log .Default .Info (ctx , color .Bold .Render ("Planned changes summary" )+ " for release %q (namespace: %q):" , releaseName , releaseNamespace )
488+ log .Default .Info (ctx , color .Bold .Render ("Planned changes summary" )+ " for release %q (namespace: %q):" , planArtifact . Release . Name , planArtifact . Release . Namespace )
483489
484490 for _ , changeType := range []string {"create" , "recreate" , "update" , "blind apply" , "delete" } {
485- logSummaryLine (ctx , changes , changeType )
491+ logSummaryLine (ctx , planArtifact . Data . Changes , changeType )
486492 }
487493
488494 log .Default .Info (ctx , "" )
0 commit comments