Skip to content

Commit 1533d82

Browse files
authored
chore: fix check kb upgrade release status in 0.9 (#493)
1 parent ade33b4 commit 1533d82

File tree

6 files changed

+64
-120
lines changed

6 files changed

+64
-120
lines changed

addons

Submodule addons updated 1826 files

pkg/cmd/kubeblocks/upgrade.go

+1-16
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"github.com/hashicorp/go-version"
2929
"github.com/pkg/errors"
3030
"github.com/spf13/cobra"
31-
"helm.sh/helm/v3/pkg/release"
3231
appsv1 "k8s.io/api/apps/v1"
3332
apierrors "k8s.io/apimachinery/pkg/api/errors"
3433
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -103,26 +102,12 @@ func (o *InstallOptions) Upgrade() error {
103102
}
104103
o.HelmCfg.SetNamespace(ns)
105104
}
106-
107-
// check helm release status
105+
// get helm release
108106
KBRelease, err := helm.GetHelmRelease(o.HelmCfg, types.KubeBlocksChartName)
109107
if err != nil {
110108
return fmt.Errorf("failed to get Helm release: %v", err)
111109
}
112110

113-
// intercept status of pending, unknown, uninstalling and uninstalled.
114-
var status release.Status
115-
if KBRelease != nil && KBRelease.Info != nil {
116-
status = KBRelease.Info.Status
117-
} else {
118-
return fmt.Errorf("failed to get Helm release status: release or release info is nil")
119-
}
120-
if status.IsPending() {
121-
return fmt.Errorf("helm release status is %s. Please wait until the release status changes to ‘deployed’ before upgrading KubeBlocks", status.String())
122-
} else if status != release.StatusDeployed && status != release.StatusFailed && status != release.StatusSuperseded {
123-
return fmt.Errorf("helm release status is %s. Please fix the release before upgrading KubeBlocks", status.String())
124-
}
125-
126111
o.Version = util.TrimVersionPrefix(o.Version)
127112
// check flags already been set
128113
if o.Version == "" && helm.ValueOptsIsEmpty(&o.ValueOpts) {

pkg/cmd/kubeblocks/upgrade_test.go

+1-75
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@ package kubeblocks
2222
import (
2323
. "github.com/onsi/ginkgo/v2"
2424
. "github.com/onsi/gomega"
25+
"github.com/spf13/cobra"
2526
"helm.sh/helm/v3/pkg/action"
2627
"helm.sh/helm/v3/pkg/chart"
2728
"helm.sh/helm/v3/pkg/release"
28-
29-
"github.com/spf13/cobra"
3029
appsv1 "k8s.io/api/apps/v1"
3130
"k8s.io/cli-runtime/pkg/genericiooptions"
3231
clientfake "k8s.io/client-go/rest/fake"
@@ -176,77 +175,4 @@ var _ = Describe("kubeblocks upgrade", func() {
176175
})
177176
})
178177

179-
Context("upgrade from different status", func() {
180-
BeforeEach(func() {
181-
streams, _, _, _ = genericiooptions.NewTestIOStreams()
182-
tf = cmdtesting.NewTestFactory().WithNamespace(namespace)
183-
tf.Client = &clientfake.RESTClient{}
184-
cfg = helm.NewFakeConfig(namespace)
185-
actionCfg, _ = helm.NewActionConfig(cfg)
186-
})
187-
188-
AfterEach(func() {
189-
helm.ResetFakeActionConfig()
190-
tf.Cleanup()
191-
})
192-
193-
mockKubeBlocksDeploy := func() *appsv1.Deployment {
194-
deploy := &appsv1.Deployment{}
195-
deploy.SetLabels(map[string]string{
196-
"app.kubernetes.io/component": "apps",
197-
"app.kubernetes.io/name": types.KubeBlocksChartName,
198-
"app.kubernetes.io/version": "0.3.0",
199-
})
200-
return deploy
201-
}
202-
It("run upgrade", func() {
203-
testCase := []struct {
204-
status release.Status
205-
checkResult bool
206-
}{
207-
{release.StatusDeployed, true},
208-
{release.StatusSuperseded, true},
209-
{release.StatusFailed, true},
210-
{release.StatusUnknown, false},
211-
{release.StatusUninstalled, false},
212-
{release.StatusUninstalling, false},
213-
{release.StatusPendingInstall, false},
214-
{release.StatusPendingUpgrade, false},
215-
{release.StatusPendingRollback, false},
216-
}
217-
218-
for i := range testCase {
219-
actionCfg, _ = helm.NewActionConfig(cfg)
220-
err := actionCfg.Releases.Create(&release.Release{
221-
Name: testing.KubeBlocksChartName,
222-
Namespace: namespace,
223-
Version: 1,
224-
Info: &release.Info{
225-
Status: testCase[i].status,
226-
},
227-
Chart: &chart.Chart{},
228-
})
229-
Expect(err).Should(BeNil())
230-
o := &InstallOptions{
231-
Options: Options{
232-
IOStreams: streams,
233-
HelmCfg: cfg,
234-
Namespace: "default",
235-
Client: testing.FakeClientSet(mockKubeBlocksDeploy()),
236-
Dynamic: testing.FakeDynamicClient(),
237-
},
238-
Version: version.DefaultKubeBlocksVersion,
239-
Check: false,
240-
}
241-
if testCase[i].checkResult {
242-
Expect(o.Upgrade()).Should(Succeed())
243-
} else {
244-
Expect(o.Upgrade()).Should(HaveOccurred())
245-
}
246-
helm.ResetFakeActionConfig()
247-
}
248-
249-
})
250-
})
251-
252178
})

pkg/util/helm/errors.go

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
// Implementing errors should be more friendly to downstream handlers
3434

3535
var ErrReleaseNotDeployed = fmt.Errorf("release: not in deployed status")
36+
var ErrReleaseNotReadyForUpgrade = fmt.Errorf("release: not in deployed, failed or superseded status")
3637

3738
func ReleaseNotFound(err error) bool {
3839
if err == nil {

pkg/util/helm/helm.go

+25-1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,30 @@ func RemoveRepo(r *repo.Entry) error {
156156
return nil
157157
}
158158

159+
// GetInstalledForUpgrade gets helm package release info and check the status.
160+
func (i *InstallOpts) GetInstalledForUpgrade(cfg *action.Configuration) (*release.Release, error) {
161+
res, err := action.NewGet(cfg).Run(i.Name)
162+
if err != nil {
163+
return nil, err
164+
}
165+
if res == nil {
166+
return nil, driver.ErrReleaseNotFound
167+
}
168+
// intercept status of pending, unknown, uninstalling and uninstalled.
169+
var status release.Status
170+
if res.Info != nil {
171+
status = res.Info.Status
172+
} else {
173+
return nil, fmt.Errorf("failed to get Helm release status: release or release info is nil")
174+
}
175+
if status.IsPending() {
176+
return nil, errors.Wrapf(ErrReleaseNotReadyForUpgrade, "helm release status is %s. Please wait until the release status changes to ‘deployed’ before upgrading KubeBlocks", status.String())
177+
} else if status != release.StatusDeployed && status != release.StatusFailed && status != release.StatusSuperseded {
178+
return nil, errors.Wrapf(ErrReleaseNotReadyForUpgrade, "helm release status is %s. Please fix the release before upgrading KubeBlocks,uninstall and install kubeblocks could be a way to fix error", status.String())
179+
}
180+
return res, nil
181+
}
182+
159183
// GetInstalled gets helm package release info if installed.
160184
func (i *InstallOpts) GetInstalled(cfg *action.Configuration) (*release.Release, error) {
161185
res, err := action.NewGet(cfg).Run(i.Name)
@@ -510,7 +534,7 @@ func (i *InstallOpts) Upgrade(cfg *Config) error {
510534
}
511535

512536
func (i *InstallOpts) tryUpgrade(cfg *action.Configuration) (*release.Release, error) {
513-
installed, err := i.GetInstalled(cfg)
537+
installed, err := i.GetInstalledForUpgrade(cfg)
514538
if err != nil {
515539
return nil, err
516540
}

pkg/util/helm/helm_test.go

+35-27
Original file line numberDiff line numberDiff line change
@@ -132,34 +132,42 @@ var _ = Describe("helm util", func() {
132132
Expect(o.Uninstall(cfg)).Should(HaveOccurred()) // release not found
133133
})
134134

135-
It("should fail at fetching charts when release is already deployed", func() {
136-
err := actionCfg.Releases.Create(&release.Release{
137-
Name: o.Name,
138-
Version: 1,
139-
Info: &release.Info{
140-
Status: release.StatusDeployed,
141-
},
142-
Chart: &chart.Chart{},
143-
})
144-
Expect(err).Should(BeNil())
145-
_, err = o.tryUpgrade(actionCfg)
146-
Expect(err).Should(HaveOccurred()) // failed at fetching charts
147-
Expect(o.tryUninstall(actionCfg)).Should(BeNil()) // release exists
148-
})
135+
It("should fail when status is not one of deployed, failed and superseded.", func() {
136+
testCase := []struct {
137+
status release.Status
138+
checkResult bool
139+
}{
140+
// deployed, failed and superseded
141+
{release.StatusDeployed, true},
142+
{release.StatusSuperseded, true},
143+
{release.StatusFailed, true},
144+
// others
145+
{release.StatusUnknown, false},
146+
{release.StatusUninstalled, false},
147+
{release.StatusUninstalling, false},
148+
{release.StatusPendingInstall, false},
149+
{release.StatusPendingUpgrade, false},
150+
{release.StatusPendingRollback, false},
151+
}
149152

150-
It("should fail when chart is already deployed", func() {
151-
err := actionCfg.Releases.Create(&release.Release{
152-
Name: o.Name,
153-
Version: 1,
154-
Info: &release.Info{
155-
Status: release.StatusFailed,
156-
},
157-
Chart: &chart.Chart{},
158-
})
159-
Expect(err).Should(BeNil())
160-
_, err = o.tryUpgrade(actionCfg)
161-
Expect(errors.Is(err, ErrReleaseNotDeployed)).Should(BeTrue())
162-
Expect(o.tryUninstall(actionCfg)).Should(BeNil()) // release exists
153+
for i := range testCase {
154+
err := actionCfg.Releases.Create(&release.Release{
155+
Name: o.Name,
156+
Version: 1,
157+
Info: &release.Info{
158+
Status: testCase[i].status,
159+
},
160+
Chart: &chart.Chart{},
161+
})
162+
Expect(err).Should(BeNil())
163+
_, err = o.tryUpgrade(actionCfg)
164+
if testCase[i].checkResult {
165+
Expect(errors.Is(err, ErrReleaseNotReadyForUpgrade)).Should(BeFalse())
166+
} else {
167+
Expect(errors.Is(err, ErrReleaseNotReadyForUpgrade)).Should(BeTrue())
168+
}
169+
Expect(o.tryUninstall(actionCfg)).Should(BeNil()) // release exists
170+
}
163171
})
164172
})
165173

0 commit comments

Comments
 (0)