Skip to content

Commit 88607b3

Browse files
[helm] revert changes made to release equality comparison (#5097)
* Revert "fix: issue-5041 (#5042)" This reverts commit 57ac0fe. Signed-off-by: varshaprasad96 <[email protected]> * Revert "fix(helm): properly compare existing and candidate releases (#4937)" This reverts commit cae12a2. Signed-off-by: varshaprasad96 <[email protected]> * add changelog fragment Signed-off-by: varshaprasad96 <[email protected]>
1 parent 820764f commit 88607b3

File tree

15 files changed

+41
-225
lines changed

15 files changed

+41
-225
lines changed
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# entries is a list of entries to include in
2+
# release notes and/or the migration guide
3+
entries:
4+
- description: >
5+
For helm-based operators, reverted the following PRs which modified helm release
6+
equality comparison.
7+
- https://github.com/operator-framework/operator-sdk/pull/5042
8+
- https://github.com/operator-framework/operator-sdk/pull/4937
9+
10+
# kind is one of:
11+
# - addition
12+
# - change
13+
# - deprecation
14+
# - removal
15+
# - bugfix
16+
kind: change
17+
18+
# Is this a breaking change?
19+
breaking: false
20+

Diff for: internal/helm/release/manager.go

+15-41
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"encoding/json"
2121
"errors"
2222
"fmt"
23-
"reflect"
2423
"strings"
2524

2625
jsonpatch "gomodules.xyz/jsonpatch/v3"
@@ -33,7 +32,6 @@ import (
3332
"helm.sh/helm/v3/pkg/storage/driver"
3433
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3534
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
36-
apiequality "k8s.io/apimachinery/pkg/api/equality"
3735
apierrors "k8s.io/apimachinery/pkg/api/errors"
3836
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3937
"k8s.io/apimachinery/pkg/runtime"
@@ -127,54 +125,22 @@ func (m *manager) Sync(ctx context.Context) error {
127125
m.deployedRelease = deployedRelease
128126
m.isInstalled = true
129127

130-
m.isUpgradeRequired, err = m.isUpgrade(deployedRelease)
128+
// Get the next candidate release to determine if an upgrade is necessary.
129+
candidateRelease, err := m.getCandidateRelease(m.namespace, m.releaseName, m.chart, m.values)
131130
if err != nil {
132-
return fmt.Errorf("failed to get upgrade status: %w", err)
131+
return fmt.Errorf("failed to get candidate release: %w", err)
133132
}
133+
if deployedRelease.Manifest != candidateRelease.Manifest {
134+
m.isUpgradeRequired = true
135+
}
136+
134137
return nil
135138
}
136139

137140
func notFoundErr(err error) bool {
138141
return err != nil && strings.Contains(err.Error(), "not found")
139142
}
140143

141-
// This is caused by the different logic of loading from local and loading from secret
142-
// For example, the Raw field, which has the tag `json:"-"`, causes the Unmarshal to be lost when it into Release
143-
// We need to make them follow the JSON tag
144-
// see: https://github.com/helm/helm/blob/cf0c6fed519d48101cd69ce01a355125215ee46f/pkg/storage/driver/util.go#L81
145-
func equalJSONStruct(a, b interface{}) (bool, error) {
146-
if reflect.ValueOf(a).IsNil() || reflect.ValueOf(b).IsNil() {
147-
return apiequality.Semantic.DeepEqual(a, b), nil
148-
}
149-
150-
aBuf, bBuf := &bytes.Buffer{}, &bytes.Buffer{}
151-
err := json.NewEncoder(aBuf).Encode(a)
152-
if err != nil {
153-
return false, err
154-
}
155-
err = json.NewEncoder(bBuf).Encode(b)
156-
return aBuf.String() == bBuf.String(), err
157-
}
158-
159-
func (m manager) isUpgrade(deployedRelease *rpb.Release) (bool, error) {
160-
if deployedRelease == nil {
161-
return false, nil
162-
}
163-
164-
// Judging whether to skip updates
165-
skip := m.namespace == deployedRelease.Namespace
166-
skip = skip && m.releaseName == deployedRelease.Name
167-
168-
ok, err := equalJSONStruct(m.chart, deployedRelease.Chart)
169-
if err != nil {
170-
return false, err
171-
}
172-
skip = skip && ok
173-
174-
ok, err = equalJSONStruct(m.values, deployedRelease.Config)
175-
return !(skip && ok), err
176-
}
177-
178144
func (m manager) getDeployedRelease() (*rpb.Release, error) {
179145
deployedRelease, err := m.storageBackend.Deployed(m.releaseName)
180146
if err != nil {
@@ -186,6 +152,14 @@ func (m manager) getDeployedRelease() (*rpb.Release, error) {
186152
return deployedRelease, nil
187153
}
188154

155+
func (m manager) getCandidateRelease(namespace, name string, chart *cpb.Chart,
156+
values map[string]interface{}) (*rpb.Release, error) {
157+
upgrade := action.NewUpgrade(m.actionConfig)
158+
upgrade.Namespace = namespace
159+
upgrade.DryRun = true
160+
return upgrade.Run(name, chart, values)
161+
}
162+
189163
// InstallRelease performs a Helm release install.
190164
func (m manager) InstallRelease(ctx context.Context, opts ...InstallOption) (*rpb.Release, error) {
191165
install := action.NewInstall(m.actionConfig)

Diff for: internal/helm/release/manager_test.go

+6-91
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,18 @@
1515
package release
1616

1717
import (
18-
"bytes"
19-
"encoding/json"
2018
"testing"
2119

22-
"github.com/stretchr/testify/assert"
23-
cpb "helm.sh/helm/v3/pkg/chart"
24-
lpb "helm.sh/helm/v3/pkg/chart/loader"
25-
rpb "helm.sh/helm/v3/pkg/release"
20+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
21+
apitypes "k8s.io/apimachinery/pkg/types"
22+
"k8s.io/cli-runtime/pkg/resource"
23+
2624
appsv1 "k8s.io/api/apps/v1"
2725
v1 "k8s.io/api/core/v1"
2826
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27+
28+
"github.com/stretchr/testify/assert"
3029
"k8s.io/apimachinery/pkg/runtime"
31-
apitypes "k8s.io/apimachinery/pkg/types"
32-
"k8s.io/cli-runtime/pkg/resource"
3330
)
3431

3532
func newTestUnstructured(containers []interface{}) *unstructured.Unstructured {
@@ -216,85 +213,3 @@ func TestManagerGenerateStrategicMergePatch(t *testing.T) {
216213
assert.Equal(t, test.patch, string(diff))
217214
}
218215
}
219-
220-
func TestManagerisUpgrade(t *testing.T) {
221-
tests := []struct {
222-
name string
223-
releaseName string
224-
releaseNs string
225-
values map[string]interface{}
226-
chart *cpb.Chart
227-
deployedRelease *rpb.Release
228-
want bool
229-
}{
230-
{
231-
name: "ok",
232-
releaseName: "deployed",
233-
releaseNs: "deployed-ns",
234-
values: map[string]interface{}{"key": "value"},
235-
chart: newTestChart(t, "./testdata/simple"),
236-
deployedRelease: newTestRelease(newTestChart(t, "./testdata/simple"), map[string]interface{}{"key": "value"}, "deployed", "deployed-ns"),
237-
want: false,
238-
},
239-
{
240-
name: "different chart",
241-
releaseName: "deployed",
242-
releaseNs: "deployed-ns",
243-
values: map[string]interface{}{"key": "value"},
244-
chart: newTestChart(t, "./testdata/simple"),
245-
deployedRelease: newTestRelease(newTestChart(t, "./testdata/simpledf"), map[string]interface{}{"key": "value"}, "deployed", "deployed-ns"),
246-
want: true,
247-
},
248-
{
249-
name: "different values",
250-
releaseName: "deployed",
251-
releaseNs: "deployed-ns",
252-
values: map[string]interface{}{"key": "1", "int": int32(1)},
253-
chart: newTestChart(t, "./testdata/simple"),
254-
deployedRelease: newTestRelease(newTestChart(t, "./testdata/simple"), map[string]interface{}{"key": "", "int": int64(1)}, "deployed", "deployed-ns"),
255-
want: true,
256-
},
257-
{
258-
name: "nil values",
259-
releaseName: "deployed",
260-
releaseNs: "deployed-ns",
261-
values: nil,
262-
chart: newTestChart(t, "./testdata/simple"),
263-
deployedRelease: newTestRelease(newTestChart(t, "./testdata/simple"), map[string]interface{}{}, "deployed", "deployed-ns"),
264-
want: false,
265-
},
266-
}
267-
for _, test := range tests {
268-
t.Run(test.name, func(t *testing.T) {
269-
m := manager{
270-
releaseName: test.releaseName,
271-
namespace: test.releaseNs,
272-
values: test.values,
273-
chart: test.chart,
274-
}
275-
isUpgrade, err := m.isUpgrade(test.deployedRelease)
276-
assert.Equal(t, test.want, isUpgrade)
277-
assert.Equal(t, nil, err)
278-
})
279-
}
280-
}
281-
282-
func newTestChart(t *testing.T, path string) *cpb.Chart {
283-
chart, err := lpb.Load(path)
284-
assert.Nil(t, err)
285-
return chart
286-
}
287-
288-
func newTestRelease(chart *cpb.Chart, values map[string]interface{}, name, namespace string) *rpb.Release { // nolint: unparam
289-
release := rpb.Mock(&rpb.MockReleaseOptions{
290-
Name: name,
291-
Namespace: namespace,
292-
Version: 1,
293-
})
294-
295-
buffer := &bytes.Buffer{}
296-
_ = json.NewEncoder(buffer).Encode(chart)
297-
_ = json.NewDecoder(buffer).Decode(release.Chart)
298-
release.Config = values
299-
return release
300-
}

Diff for: internal/helm/release/testdata/simple/.helmignore

-21
This file was deleted.

Diff for: internal/helm/release/testdata/simple/Chart.yaml

-8
This file was deleted.

Diff for: internal/helm/release/testdata/simple/templates/NOTES.txt

-1
This file was deleted.

Diff for: internal/helm/release/testdata/simple/templates/_helpers.tpl

-7
This file was deleted.

Diff for: internal/helm/release/testdata/simple/templates/secrets.yaml

-8
This file was deleted.

Diff for: internal/helm/release/testdata/simple/values.yaml

-1
This file was deleted.

Diff for: internal/helm/release/testdata/simpledf/.helmignore

-21
This file was deleted.

Diff for: internal/helm/release/testdata/simpledf/Chart.yaml

-8
This file was deleted.

Diff for: internal/helm/release/testdata/simpledf/templates/NOTES.txt

-1
This file was deleted.

Diff for: internal/helm/release/testdata/simpledf/templates/_helpers.tpl

-7
This file was deleted.

Diff for: internal/helm/release/testdata/simpledf/templates/secrets.yaml

-8
This file was deleted.

Diff for: internal/helm/release/testdata/simpledf/values.yaml

-2
This file was deleted.

0 commit comments

Comments
 (0)