Skip to content

Commit d6ab5ae

Browse files
ldmonsteryalosevCopilot
authored
[addon-operator] fix/maintenance mode restart fix (#596)
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com> Signed-off-by: Yuriy Losev <yuriy.losev@flant.com> Co-authored-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com> Co-authored-by: Yuriy Losev <yuriy.losev@flant.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 1d84211 commit d6ab5ae

File tree

11 files changed

+129
-41
lines changed

11 files changed

+129
-41
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ jobs:
3838
run: |
3939
export GOOS=linux
4040
41-
go build ./cmd/addon-operator
41+
go build ./cmd/addon-operator

.github/workflows/tests.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,4 @@ jobs:
4141
4242
go test \
4343
--race \
44-
-tags use_libjq \
45-
./cmd/... ./pkg/...
44+
./cmd/... ./pkg/...

Dockerfile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Prebuilt libjq.
2+
FROM --platform=${TARGETPLATFORM:-linux/amd64} flant/jq:b6be13d5-musl as libjq
3+
4+
# Go builder.
5+
16
FROM --platform=${TARGETPLATFORM:-linux/amd64} golang:1.23-alpine AS builder
27

38

@@ -9,16 +14,17 @@ ADD go.mod go.sum /app/
914
WORKDIR /app
1015
RUN go mod download
1116

17+
COPY --from=libjq /libjq /libjq
1218
ADD . /app
1319

1420
# Clone shell-operator to get frameworks
1521
RUN git clone https://github.com/flant/shell-operator shell-operator-clone && \
1622
cd shell-operator-clone && \
17-
git checkout v1.7.0
23+
git checkout v1.7.2
1824

1925
RUN shellOpVer=$(go list -m all | grep shell-operator | cut -d' ' -f 2-) \
2026
GOOS=linux \
21-
go build -ldflags="-s -w -X 'github.com/flant/shell-operator/pkg/app.Version=$shellOpVer' -X 'github.com/flant/addon-operator/pkg/app.Version=$appVersion'" \
27+
go build -ldflags="-linkmode external -extldflags '-static' -s -w -X 'github.com/flant/shell-operator/pkg/app.Version=$shellOpVer' -X 'github.com/flant/addon-operator/pkg/app.Version=$appVersion'" \
2228
-o addon-operator \
2329
./cmd/addon-operator
2430

@@ -40,6 +46,7 @@ RUN apk --no-cache add ca-certificates bash sed tini && \
4046
wget https://get.helm.sh/helm-v3.10.3-${helmArch}.tar.gz -O /helm.tgz && \
4147
tar -z -x -C /bin -f /helm.tgz --strip-components=1 ${helmArch}/helm && \
4248
rm -f /helm.tgz
49+
COPY --from=libjq /bin/jq /usr/bin
4350
COPY --from=builder /app/addon-operator /
4451
COPY --from=builder /app/post-renderer /
4552
COPY --from=builder /app/shell-operator-clone/frameworks/shell/ /framework/shell/
@@ -50,4 +57,4 @@ WORKDIR /
5057
RUN mkdir /global-hooks /modules
5158
ENV MODULES_DIR /modules
5259
ENV GLOBAL_HOOKS_DIR /global-hooks
53-
ENTRYPOINT ["/sbin/tini", "--", "/addon-operator"]
60+
ENTRYPOINT ["/sbin/tini", "--", "/addon-operator"]

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/dominikbraun/graph v0.23.0
1010
github.com/ettle/strcase v0.2.0
1111
github.com/flant/kube-client v1.3.0
12-
github.com/flant/shell-operator v1.7.1
12+
github.com/flant/shell-operator v1.7.2
1313
github.com/go-chi/chi/v5 v5.2.1
1414
github.com/go-openapi/loads v0.19.5
1515
github.com/go-openapi/spec v0.19.8
@@ -176,7 +176,7 @@ require (
176176
golang.org/x/net v0.38.0 // indirect
177177
golang.org/x/oauth2 v0.21.0 // indirect
178178
golang.org/x/sync v0.12.0 // indirect
179-
golang.org/x/sys v0.31.0 // indirect
179+
golang.org/x/sys v0.32.0 // indirect
180180
golang.org/x/term v0.30.0 // indirect
181181
golang.org/x/text v0.23.0 // indirect
182182
golang.org/x/time v0.11.0 // indirect

go.sum

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ github.com/flant/go-openapi-validate v0.19.12-flant.1 h1:GuB9XEfiLHq3M7fafRLq1AW
144144
github.com/flant/go-openapi-validate v0.19.12-flant.1/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4=
145145
github.com/flant/kube-client v1.3.0 h1:iVxwpUZO4AhURkq6n44qfzp0Bjs5WatzTtJrfxeRDkE=
146146
github.com/flant/kube-client v1.3.0/go.mod h1:yaFoNwyomNm0/OLXRxGYvR7or2pfLv9M9qPDSPPwljI=
147-
github.com/flant/shell-operator v1.7.1 h1:H4Kxbuoms2Vrmt81Faa7pHlp0Emmb4chgTXWCrEVBEI=
148-
github.com/flant/shell-operator v1.7.1/go.mod h1:RK6HoINBm3V/AOiZEQA+EUPFiJcb46qG2ebKeZogANI=
147+
github.com/flant/shell-operator v1.7.2 h1:7qyRV7a5yaX0hQt9wTwbxwBv3sdDrP2Fw1KozOvaXV0=
148+
github.com/flant/shell-operator v1.7.2/go.mod h1:7IDbBSRdoWtKojGnhxnb3JlNF97Q7+mbR0UXhxF5yGg=
149149
github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU=
150150
github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw=
151151
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
@@ -297,8 +297,8 @@ github.com/google/go-containerregistry v0.17.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY
297297
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
298298
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
299299
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
300-
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
301-
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
300+
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
301+
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
302302
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
303303
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
304304
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -462,9 +462,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
462462
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
463463
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
464464
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
465-
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
466-
github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0=
467-
github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
465+
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
466+
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
468467
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
469468
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
470469
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -634,6 +633,8 @@ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lI
634633
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
635634
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
636635
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
636+
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
637+
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
637638
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
638639
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
639640
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
@@ -720,8 +721,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
720721
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
721722
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
722723
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
723-
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
724-
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
724+
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
725+
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
725726
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
726727
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
727728
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -754,8 +755,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
754755
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
755756
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
756757
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
757-
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
758-
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
758+
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
759+
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
759760
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
760761
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
761762
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

pkg/helm/client/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type HelmClient interface {
1010
Render(releaseName string, chart string, valuesPaths []string, setValues []string, namespace string, debug bool) (string, error)
1111
GetReleaseValues(releaseName string) (utils.Values, error)
1212
GetReleaseChecksum(releaseName string) (string, error)
13+
GetReleaseLabels(releaseName, labelName string) (string, error)
1314
DeleteRelease(releaseName string) error
1415
ListReleasesNames() ([]string, error)
1516
IsReleaseExists(releaseName string) (bool, error)

pkg/helm/helm3/helm3.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package helm3
22

33
import (
44
"bytes"
5+
"errors"
56
"fmt"
67
"log/slog"
78
"os/exec"
@@ -191,12 +192,42 @@ func (h *Helm3Client) UpgradeRelease(releaseName string, chart string, valuesPat
191192
return nil
192193
}
193194

195+
var ErrLabelIsNotFound = errors.New("label is not found")
196+
197+
func (h *Helm3Client) GetReleaseLabels(releaseName, labelName string) (string, error) {
198+
args := []string{
199+
"get", "manifest", releaseName,
200+
"--namespace", h.Namespace,
201+
"--output", "yaml",
202+
}
203+
204+
stdout, stderr, err := h.cmd(args...)
205+
if err != nil {
206+
return "", fmt.Errorf("cannot get manifest of helm release %s: %s\n%s %s", releaseName, err, stdout, stderr)
207+
}
208+
209+
lines := strings.Split(stdout, "\n")
210+
for _, line := range lines {
211+
if strings.Contains(line, labelName) {
212+
split := strings.Split(line, ":")
213+
if len(split) < 2 {
214+
return "", fmt.Errorf("cannot parse label %s from helm release %s: %s", labelName, releaseName, line)
215+
}
216+
217+
return strings.TrimSpace(split[1]), nil
218+
}
219+
}
220+
221+
return "", ErrLabelIsNotFound
222+
}
223+
194224
func (h *Helm3Client) GetReleaseValues(releaseName string) (utils.Values, error) {
195225
args := []string{
196226
"get", "values", releaseName,
197227
"--namespace", h.Namespace,
198228
"--output", "yaml",
199229
}
230+
200231
stdout, stderr, err := h.cmd(args...)
201232
if err != nil {
202233
return nil, fmt.Errorf("cannot get values of helm release %s: %s\n%s %s", releaseName, err, stdout, stderr)
@@ -215,6 +246,7 @@ func (h *Helm3Client) GetReleaseChecksum(releaseName string) (string, error) {
215246
"get", "manifest", releaseName,
216247
"--namespace", h.Namespace,
217248
}
249+
218250
stdout, stderr, err := h.cmd(args...)
219251
if err != nil {
220252
return "", fmt.Errorf("cannot get manifest of helm release %s: %s\n%s %s", releaseName, err, stdout, stderr)

pkg/helm/helm3lib/helm3lib.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,23 @@ func (h *LibClient) GetReleaseValues(releaseName string) (utils.Values, error) {
358358
return gv.Run(releaseName)
359359
}
360360

361+
var ErrLabelIsNotFound = errors.New("label is not found")
362+
363+
func (h *LibClient) GetReleaseLabels(releaseName, labelName string) (string, error) {
364+
gv := action.NewGet(actionConfig)
365+
rel, err := gv.Run(releaseName)
366+
if err != nil {
367+
return "", fmt.Errorf("helm get failed: %s", err)
368+
}
369+
370+
if value, ok := rel.Labels[labelName]; ok {
371+
return value, nil
372+
}
373+
374+
return "", ErrLabelIsNotFound
375+
}
376+
377+
// Deprecated: use GetReleaseLabels instead
361378
func (h *LibClient) GetReleaseChecksum(releaseName string) (string, error) {
362379
gv := action.NewGet(actionConfig)
363380
rel, err := gv.Run(releaseName)

pkg/module_manager/models/modules/basic.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ func (bm *BasicModule) ResetState() {
191191
bm.l.Lock()
192192
var maintenanceState MaintenanceState
193193

194-
if bm.state.maintenanceState == UnmanagedEnforced {
195-
maintenanceState = UnmanagedEnabled
194+
if bm.state.maintenanceState == Unmanaged {
195+
maintenanceState = Unmanaged
196196
}
197197

198198
bm.state = &moduleState{
@@ -550,7 +550,7 @@ func (bm *BasicModule) SetMaintenanceState(state utils.Maintenance) {
550550
switch state {
551551
case utils.NoResourceReconciliation:
552552
if bm.state.maintenanceState == Managed {
553-
bm.state.maintenanceState = UnmanagedEnabled
553+
bm.state.maintenanceState = Unmanaged
554554
}
555555
case utils.Managed:
556556
if bm.state.maintenanceState != Managed {
@@ -560,10 +560,10 @@ func (bm *BasicModule) SetMaintenanceState(state utils.Maintenance) {
560560
bm.l.Unlock()
561561
}
562562

563-
func (bm *BasicModule) SetUnmanagedEnforced() {
563+
func (bm *BasicModule) SetUnmanaged() {
564564
bm.l.Lock()
565-
if bm.state.maintenanceState == UnmanagedEnabled {
566-
bm.state.maintenanceState = UnmanagedEnforced
565+
if bm.state.maintenanceState == Managed {
566+
bm.state.maintenanceState = Unmanaged
567567
}
568568
bm.l.Unlock()
569569
}
@@ -1290,10 +1290,8 @@ type MaintenanceState int
12901290
const (
12911291
// Module runs in a normal mode
12921292
Managed MaintenanceState = iota
1293-
// Next helm run will enforce NoResourceReconciliation mode (removes heritage labels and stops resource informer)
1294-
UnmanagedEnabled
1295-
// All consequent helm runs are inhibited
1296-
UnmanagedEnforced
1293+
// All consequent helm runs are inhibited (heritage labels are removed and resource informer is stopped)
1294+
Unmanaged = 1
12971295
)
12981296

12991297
type moduleState struct {

0 commit comments

Comments
 (0)