@ -19,12 +19,13 @@ package action
import (
import (
"bytes"
"bytes"
"context"
"context"
"errors"
"fmt"
"fmt"
"strings"
"strings"
"sync"
"sync"
"time"
"time"
"github.com/pkg/errors"
githubErrors "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/cli-runtime/pkg/resource"
@ -274,15 +275,15 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR
// Checking for removed Kubernetes API error so can provide a more informative error message to the user
// Checking for removed Kubernetes API error so can provide a more informative error message to the user
// Ref: https://github.com/helm/helm/issues/7219
// Ref: https://github.com/helm/helm/issues/7219
if strings . Contains ( err . Error ( ) , "unable to recognize \"\": no matches for kind" ) {
if strings . Contains ( err . Error ( ) , "unable to recognize \"\": no matches for kind" ) {
return upgradedRelease , e rrors. Wrap ( err , "current release manifest contains removed kubernetes api(s) for this " +
return upgradedRelease , githubE rrors. Wrap ( err , "current release manifest contains removed kubernetes api(s) for this " +
"kubernetes version and it is therefore unable to build the kubernetes " +
"kubernetes version and it is therefore unable to build the kubernetes " +
"objects for performing the diff. error from kubernetes" )
"objects for performing the diff. error from kubernetes" )
}
}
return upgradedRelease , e rrors. Wrap ( err , "unable to build kubernetes objects from current release manifest" )
return upgradedRelease , githubE rrors. Wrap ( err , "unable to build kubernetes objects from current release manifest" )
}
}
target , err := u . cfg . KubeClient . Build ( bytes . NewBufferString ( upgradedRelease . Manifest ) , ! u . DisableOpenAPIValidation )
target , err := u . cfg . KubeClient . Build ( bytes . NewBufferString ( upgradedRelease . Manifest ) , ! u . DisableOpenAPIValidation )
if err != nil {
if err != nil {
return upgradedRelease , e rrors. Wrap ( err , "unable to build kubernetes objects from new release manifest" )
return upgradedRelease , githubE rrors. Wrap ( err , "unable to build kubernetes objects from new release manifest" )
}
}
// It is safe to use force only on target because these are resources currently rendered by the chart.
// It is safe to use force only on target because these are resources currently rendered by the chart.
@ -306,7 +307,7 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR
toBeUpdated , err := existingResourceConflict ( toBeCreated , upgradedRelease . Name , upgradedRelease . Namespace )
toBeUpdated , err := existingResourceConflict ( toBeCreated , upgradedRelease . Name , upgradedRelease . Namespace )
if err != nil {
if err != nil {
return nil , e rrors. Wrap ( err , "rendered manifests contain a resource that already exists. Unable to continue with update" )
return nil , githubE rrors. Wrap ( err , "rendered manifests contain a resource that already exists. Unable to continue with update" )
}
}
toBeUpdated . Visit ( func ( r * resource . Info , err error ) error {
toBeUpdated . Visit ( func ( r * resource . Info , err error ) error {
@ -452,7 +453,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
for _ , e := range errs {
for _ , e := range errs {
errorList = append ( errorList , e . Error ( ) )
errorList = append ( errorList , e . Error ( ) )
}
}
return rel , e rrors. Wrapf ( fmt . Errorf ( "unable to cleanup resources: %s" , strings . Join ( errorList , ", " ) ) , "an error occurred while cleaning up resources. original upgrade error: %s" , err )
return rel , githubE rrors. Wrapf ( fmt . Errorf ( "unable to cleanup resources: %s" , strings . Join ( errorList , ", " ) ) , "an error occurred while cleaning up resources. original upgrade error: %s" , err )
}
}
u . cfg . Log ( "Resource cleanup complete" )
u . cfg . Log ( "Resource cleanup complete" )
}
}
@ -464,7 +465,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
hist := NewHistory ( u . cfg )
hist := NewHistory ( u . cfg )
fullHistory , herr := hist . Run ( rel . Name )
fullHistory , herr := hist . Run ( rel . Name )
if herr != nil {
if herr != nil {
return rel , e rrors. Wrapf ( herr , "an error occurred while finding last successful release. original upgrade error: %s" , err )
return rel , githubE rrors. Wrapf ( herr , "an error occurred while finding last successful release. original upgrade error: %s" , err )
}
}
// There isn't a way to tell if a previous release was successful, but
// There isn't a way to tell if a previous release was successful, but
@ -474,7 +475,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
return r . Info . Status == release . StatusSuperseded || r . Info . Status == release . StatusDeployed
return r . Info . Status == release . StatusSuperseded || r . Info . Status == release . StatusDeployed
} ) . Filter ( fullHistory )
} ) . Filter ( fullHistory )
if len ( filteredHistory ) == 0 {
if len ( filteredHistory ) == 0 {
return rel , e rrors. Wrap ( err , "unable to find a previously successful release when attempting to rollback. original upgrade error" )
return rel , githubE rrors. Wrap ( err , "unable to find a previously successful release when attempting to rollback. original upgrade error" )
}
}
releaseutil . Reverse ( filteredHistory , releaseutil . SortByRevision )
releaseutil . Reverse ( filteredHistory , releaseutil . SortByRevision )
@ -488,9 +489,9 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
rollin . Force = u . Force
rollin . Force = u . Force
rollin . Timeout = u . Timeout
rollin . Timeout = u . Timeout
if rollErr := rollin . Run ( rel . Name ) ; rollErr != nil {
if rollErr := rollin . Run ( rel . Name ) ; rollErr != nil {
return rel , e rrors. Wrapf ( rollErr , "an error occurred while rolling back the release. original upgrade error: %s" , err )
return rel , githubE rrors. Wrapf ( rollErr , "an error occurred while rolling back the release. original upgrade error: %s" , err )
}
}
return rel , e rrors. Wrapf ( err , "release %s failed, and has been rolled back due to atomic being set" , rel . Name )
return rel , githubE rrors. Wrapf ( err , "release %s failed, and has been rolled back due to atomic being set" , rel . Name )
}
}
return rel , err
return rel , err
@ -518,7 +519,7 @@ func (u *Upgrade) reuseValues(chart *chart.Chart, current *release.Release, newV
// We have to regenerate the old coalesced values:
// We have to regenerate the old coalesced values:
oldVals , err := chartutil . CoalesceValues ( current . Chart , current . Config )
oldVals , err := chartutil . CoalesceValues ( current . Chart , current . Config )
if err != nil {
if err != nil {
return nil , e rrors. Wrap ( err , "failed to rebuild old values" )
return nil , githubE rrors. Wrap ( err , "failed to rebuild old values" )
}
}
newVals = chartutil . CoalesceTables ( newVals , current . Config )
newVals = chartutil . CoalesceTables ( newVals , current . Config )
@ -555,21 +556,21 @@ func recreate(cfg *Configuration, resources kube.ResourceList) error {
client , err := cfg . KubernetesClientSet ( )
client , err := cfg . KubernetesClientSet ( )
if err != nil {
if err != nil {
return e rrors. Wrapf ( err , "unable to recreate pods for object %s/%s because an error occurred" , res . Namespace , res . Name )
return githubE rrors. Wrapf ( err , "unable to recreate pods for object %s/%s because an error occurred" , res . Namespace , res . Name )
}
}
pods , err := client . CoreV1 ( ) . Pods ( res . Namespace ) . List ( context . Background ( ) , metav1 . ListOptions {
pods , err := client . CoreV1 ( ) . Pods ( res . Namespace ) . List ( context . Background ( ) , metav1 . ListOptions {
LabelSelector : selector . String ( ) ,
LabelSelector : selector . String ( ) ,
} )
} )
if err != nil {
if err != nil {
return e rrors. Wrapf ( err , "unable to recreate pods for object %s/%s because an error occurred" , res . Namespace , res . Name )
return githubE rrors. Wrapf ( err , "unable to recreate pods for object %s/%s because an error occurred" , res . Namespace , res . Name )
}
}
// Restart pods
// Restart pods
for _ , pod := range pods . Items {
for _ , pod := range pods . Items {
// Delete each pod for get them restarted with changed spec.
// Delete each pod for get them restarted with changed spec.
if err := client . CoreV1 ( ) . Pods ( pod . Namespace ) . Delete ( context . Background ( ) , pod . Name , * metav1 . NewPreconditionDeleteOptions ( string ( pod . UID ) ) ) ; err != nil {
if err := client . CoreV1 ( ) . Pods ( pod . Namespace ) . Delete ( context . Background ( ) , pod . Name , * metav1 . NewPreconditionDeleteOptions ( string ( pod . UID ) ) ) ; err != nil {
return e rrors. Wrapf ( err , "unable to recreate pods for object %s/%s because an error occurred" , res . Namespace , res . Name )
return githubE rrors. Wrapf ( err , "unable to recreate pods for object %s/%s because an error occurred" , res . Namespace , res . Name )
}
}
}
}
}
}