mirror of
https://github.com/helm/helm.git
synced 2026-08-07 00:21:27 +00:00
Alternative: annotation-only solution
Signed-off-by: Jacob LeGrone <git@jacob.work>
This commit is contained in:
@@ -249,6 +249,11 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
|
||||
return nil, errors.Wrap(err, "unable to build kubernetes objects from release manifest")
|
||||
}
|
||||
|
||||
err = resources.Visit(setMetadataVisitor(rel.Name, rel.Namespace))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Install requires an extra validation step of checking that resources
|
||||
// don't already exist before we actually create resources. If we continue
|
||||
// forward and create the release object with resources that already exist,
|
||||
@@ -256,7 +261,7 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
|
||||
// deleting the release because the manifest will be pointing at that
|
||||
// resource
|
||||
if !i.ClientOnly && !isUpgrade {
|
||||
toBeUpdated, err := existingResourceConflict(resources, rel.Name)
|
||||
toBeUpdated, err := existingResourceConflict(resources, rel.Name, rel.Namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendered manifests contain a resource that already exists. Unable to continue with install")
|
||||
}
|
||||
|
||||
@@ -203,6 +203,11 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
|
||||
return upgradedRelease, errors.Wrap(err, "unable to build kubernetes objects from new release manifest")
|
||||
}
|
||||
|
||||
err = target.Visit(setMetadataVisitor(upgradedRelease.Name, upgradedRelease.Namespace))
|
||||
if err != nil {
|
||||
return upgradedRelease, err
|
||||
}
|
||||
|
||||
// Do a basic diff using gvk + name to figure out what new resources are being created so we can validate they don't already exist
|
||||
existingResources := make(map[string]bool)
|
||||
for _, r := range current {
|
||||
@@ -216,7 +221,7 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea
|
||||
}
|
||||
}
|
||||
|
||||
toBeUpdated, err := existingResourceConflict(toBeCreated, upgradedRelease.Name)
|
||||
toBeUpdated, err := existingResourceConflict(toBeCreated, upgradedRelease.Name, upgradedRelease.Namespace)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "rendered manifests contain a resource that already exists. Unable to continue with update")
|
||||
}
|
||||
|
||||
@@ -22,36 +22,22 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
|
||||
"helm.sh/helm/v3/pkg/kube"
|
||||
)
|
||||
|
||||
var (
|
||||
managedByReq, _ = labels.NewRequirement("app.kubernetes.io/managed-by", selection.Equals, []string{"Helm"})
|
||||
accessor = meta.NewAccessor()
|
||||
var accessor = meta.NewAccessor()
|
||||
|
||||
const (
|
||||
helmReleaseNameAnnotation = "meta.helm.sh/release-name"
|
||||
helmReleaseNamespaceAnnotation = "meta.helm.sh/release-namespace"
|
||||
)
|
||||
|
||||
func newReleaseSelector(release string) (labels.Selector, error) {
|
||||
releaseReq, err := labels.NewRequirement("app.kubernetes.io/instance", selection.Equals, []string{release})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return labels.Parse(fmt.Sprintf("%s,%s", releaseReq, managedByReq))
|
||||
}
|
||||
|
||||
func existingResourceConflict(resources kube.ResourceList, release string) (kube.ResourceList, error) {
|
||||
sel, err := newReleaseSelector(release)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func existingResourceConflict(resources kube.ResourceList, releaseName, releaseNamespace string) (kube.ResourceList, error) {
|
||||
requireUpdate := kube.ResourceList{}
|
||||
|
||||
err = resources.Visit(func(info *resource.Info, err error) error {
|
||||
err := resources.Visit(func(info *resource.Info, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -67,13 +53,10 @@ func existingResourceConflict(resources kube.ResourceList, release string) (kube
|
||||
}
|
||||
|
||||
// Allow adoption of the resource if it already has app.kubernetes.io/instance and app.kubernetes.io/managed-by labels.
|
||||
lbls, err := accessor.Labels(existing)
|
||||
if err == nil {
|
||||
set := labels.Set(lbls)
|
||||
if sel.Matches(set) {
|
||||
requireUpdate = append(requireUpdate, info)
|
||||
return nil
|
||||
}
|
||||
anno, err := accessor.Annotations(existing)
|
||||
if err == nil && anno != nil && anno[helmReleaseNameAnnotation] == releaseName && anno[helmReleaseNamespaceAnnotation] == releaseNamespace {
|
||||
requireUpdate = append(requireUpdate, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf(
|
||||
@@ -83,3 +66,21 @@ func existingResourceConflict(resources kube.ResourceList, release string) (kube
|
||||
|
||||
return requireUpdate, err
|
||||
}
|
||||
|
||||
func setMetadataVisitor(releaseName, releaseNamespace string) resource.VisitorFunc {
|
||||
return func(info *resource.Info, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
anno, err := accessor.Annotations(info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if anno == nil {
|
||||
anno = make(map[string]string)
|
||||
}
|
||||
anno[helmReleaseNameAnnotation] = releaseName
|
||||
anno[helmReleaseNamespaceAnnotation] = releaseNamespace
|
||||
return accessor.SetAnnotations(info.Object, anno)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user