Skip to content

Commit c17322c

Browse files
feat: upgrade to support Kubernetes 1.30
- Update Go version to 1.22 - Update Kubernetes dependencies to v0.29.2 - Update controller-runtime to v0.17.2 - Update GitHub Actions to latest versions - Add improved Docker build configuration - Add context timeout handling in controllers - Add improved error handling and logging
1 parent 3f8fe12 commit c17322c

File tree

7 files changed

+91
-63
lines changed

7 files changed

+91
-63
lines changed

.github/workflows/ci.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ jobs:
1212
test:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- uses: actions/checkout@v3
16-
- uses: actions/setup-go@v3
15+
- uses: actions/checkout@v4
16+
- uses: actions/setup-go@v5
1717
with:
18-
go-version: "1.19"
18+
go-version: "1.22"
19+
check-latest: true
20+
cache: true
1921
- run: make test
2022

2123
docker-build:
2224
runs-on: ubuntu-latest
2325
steps:
24-
- uses: actions/checkout@v3
26+
- uses: actions/checkout@v4
27+
- uses: docker/setup-buildx-action@v3
2528
- run: make docker-build

.github/workflows/release.yaml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,23 @@ on:
1010
jobs:
1111
run:
1212
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
packages: write
1316
steps:
14-
- uses: actions/checkout@v3
17+
- uses: actions/checkout@v4
18+
- uses: docker/setup-buildx-action@v3
1519
- name: Login to GitHub Container Registry
16-
uses: docker/login-action@v2
20+
uses: docker/login-action@v3
1721
with:
1822
registry: ghcr.io
1923
username: ${{ github.actor }}
2024
password: ${{ secrets.GITHUB_TOKEN }}
21-
- run: make docker-build
22-
- run: make docker-push
25+
- name: Build and push
26+
uses: docker/build-push-action@v5
27+
with:
28+
context: .
29+
push: true
30+
tags: |
31+
ghcr.io/${{ github.repository }}:latest
32+
ghcr.io/${{ github.repository }}:${{ github.ref_name }}

.github/workflows/tagpr.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,21 @@ on:
77
jobs:
88
tagpr:
99
runs-on: ubuntu-latest
10+
permissions:
11+
contents: write
12+
pull-requests: write
1013
steps:
11-
- uses: actions/checkout@v3
14+
- uses: actions/checkout@v4
15+
with:
16+
fetch-depth: 0
1217
- id: tagpr
1318
name: Tagpr
1419
uses: Songmu/tagpr@v1
1520
env:
1621
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1722

1823
- name: Trigger Release Workflow(only when tagged)
19-
uses: actions/github-script@v6
24+
uses: actions/github-script@v7
2025
if: "steps.tagpr.outputs.tag != ''"
2126
with:
2227
script: |

Dockerfile

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,27 @@
1-
FROM golang:1.19 AS base
1+
# Build the manager binary
2+
FROM golang:1.22 as builder
23

34
WORKDIR /workspace
45
# Copy the Go Modules manifests
5-
COPY go.* .
6+
COPY go.mod go.mod
7+
COPY go.sum go.sum
68
# cache deps before building and copying source so that we don't need to re-download as much
79
# and so that source changes don't invalidate our downloaded layer
8-
RUN --mount=type=cache,target=/go/pkg/mod \
9-
go mod download
10+
RUN go mod download
1011

11-
FROM golangci/golangci-lint:v1.49 AS lint-base
12-
FROM base AS lint
13-
RUN --mount=target=. \
14-
--mount=from=lint-base,src=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
15-
--mount=type=cache,target=/go/pkg/mod \
16-
--mount=type=cache,target=/root/.cache/go-build \
17-
--mount=type=cache,target=/root/.cache/golangci-lint \
18-
golangci-lint run --timeout 10m0s ./...
12+
# Copy the go source
13+
COPY main.go main.go
14+
COPY api/ api/
15+
COPY controllers/ controllers/
1916

20-
FROM base AS build
21-
# Build the manager binary
22-
RUN --mount=target=. \
23-
--mount=type=cache,target=/go/pkg/mod \
24-
--mount=type=cache,target=/root/.cache/go-build \
25-
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o /out/manager main.go
17+
# Build
18+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go
2619

2720
# Use distroless as minimal base image to package the manager binary
2821
# Refer to https://github.com/GoogleContainerTools/distroless for more details
2922
FROM gcr.io/distroless/static:nonroot
3023
WORKDIR /
31-
COPY --from=build /out/manager .
24+
COPY --from=builder /workspace/manager .
25+
USER 65532:65532
3226

3327
ENTRYPOINT ["/manager"]

controllers/nodeoperation_controller.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
ctrl "sigs.k8s.io/controller-runtime"
3737
"sigs.k8s.io/controller-runtime/pkg/client"
3838
"sigs.k8s.io/controller-runtime/pkg/log"
39+
"sigs.k8s.io/controller-runtime/pkg/predicate"
3940
)
4041

4142
var controllerTaint = corev1.Taint{
@@ -87,16 +88,21 @@ type NodeOperationReconciler struct {
8788
func (r *NodeOperationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
8889
logger := log.FromContext(ctx)
8990

91+
// Add timeout to context
92+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
93+
defer cancel()
94+
9095
nodeOp := &nodeopsv1alpha1.NodeOperation{}
9196
if err := r.Get(ctx, req.NamespacedName, nodeOp); err != nil {
9297
sterr, ok := err.(*errors.StatusError)
93-
if ok && sterr.Status().Code == 404 {
98+
if ok && sterr.Status().Code == http.StatusNotFound {
9499
if err := r.removeTaints(ctx); err != nil {
100+
logger.Error(err, "failed to remove taints")
95101
return ctrl.Result{}, err
96102
}
97103
return ctrl.Result{}, nil
98104
}
99-
return ctrl.Result{}, err
105+
return ctrl.Result{}, client.IgnoreNotFound(err)
100106
}
101107

102108
var result ctrl.Result
@@ -410,7 +416,7 @@ func (r *NodeOperationReconciler) reconcileRunning(ctx context.Context, nodeOp *
410416
func (r *NodeOperationReconciler) SetupWithManager(mgr ctrl.Manager) error {
411417
r.clientset = kubernetes.NewForConfigOrDie(mgr.GetConfig())
412418
r.mutex = sync.Mutex{}
413-
// create index for NodeOperation name
419+
// Create a new indexer for jobs that references NodeOperations
414420
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &batchv1.Job{}, jobOwnerKey, func(rawObj client.Object) []string {
415421
job := rawObj.(*batchv1.Job)
416422
owner := metav1.GetControllerOf(job)
@@ -431,6 +437,7 @@ func (r *NodeOperationReconciler) SetupWithManager(mgr ctrl.Manager) error {
431437
return ctrl.NewControllerManagedBy(mgr).
432438
For(&nodeopsv1alpha1.NodeOperation{}).
433439
Owns(&batchv1.Job{}).
440+
WithEventFilter(predicate.GenerationChangedPredicate{}).
434441
Complete(r)
435442
}
436443

controllers/suite_test.go

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,20 @@ import (
3030

3131
. "github.com/onsi/ginkgo/v2"
3232
. "github.com/onsi/gomega"
33-
"sigs.k8s.io/controller-runtime/pkg/manager"
34-
35-
batchv1 "k8s.io/api/batch/v1"
36-
corev1 "k8s.io/api/core/v1"
37-
apierrors "k8s.io/apimachinery/pkg/api/errors"
38-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3933
"k8s.io/client-go/kubernetes/scheme"
4034
"k8s.io/client-go/rest"
35+
ctrl "sigs.k8s.io/controller-runtime"
4136
"sigs.k8s.io/controller-runtime/pkg/client"
4237
"sigs.k8s.io/controller-runtime/pkg/envtest"
4338
logf "sigs.k8s.io/controller-runtime/pkg/log"
4439
"sigs.k8s.io/controller-runtime/pkg/log/zap"
4540

41+
batchv1 "k8s.io/api/batch/v1"
42+
corev1 "k8s.io/api/core/v1"
43+
apierrors "k8s.io/apimachinery/pkg/api/errors"
44+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
45+
"k8s.io/client-go/rest"
46+
4647
nodeopsv1alpha1 "github.com/pfnet-research/node-operation-controller/api/v1alpha1"
4748
//+kubebuilder:scaffold:imports
4849
)
@@ -53,6 +54,8 @@ import (
5354
var cfg *rest.Config
5455
var k8sClient client.Client
5556
var testEnv *envtest.Environment
57+
var ctx context.Context
58+
var cancel context.CancelFunc
5659

5760
func TestAPIs(t *testing.T) {
5861
RegisterFailHandler(Fail)
@@ -63,12 +66,12 @@ func TestAPIs(t *testing.T) {
6366
var _ = BeforeSuite(func() {
6467
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
6568

69+
ctx, cancel = context.WithCancel(context.Background())
70+
6671
By("bootstrapping test environment")
67-
trueV := true
6872
testEnv = &envtest.Environment{
6973
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
7074
ErrorIfCRDPathMissing: true,
71-
UseExistingCluster: &trueV,
7275
}
7376

7477
var err error
@@ -85,35 +88,40 @@ var _ = BeforeSuite(func() {
8588
Expect(err).NotTo(HaveOccurred())
8689
Expect(k8sClient).NotTo(BeNil())
8790

88-
mgr, err := manager.New(cfg, manager.Options{})
89-
Expect(err).NotTo(HaveOccurred())
91+
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
92+
Scheme: scheme.Scheme,
93+
})
94+
Expect(err).ToNot(HaveOccurred())
9095

9196
err = (&NodeOperationReconciler{
92-
Client: mgr.GetClient(),
93-
Scheme: scheme.Scheme,
94-
}).SetupWithManager(mgr)
97+
Client: k8sManager.GetClient(),
98+
Scheme: k8sManager.GetScheme(),
99+
DrainInterval: 1 * time.Second,
100+
NDBRetryInterval: 1 * time.Second,
101+
}).SetupWithManager(k8sManager)
95102
Expect(err).ToNot(HaveOccurred())
96103

97104
err = (&NodeRemediationReconciler{
98-
Client: mgr.GetClient(),
99-
Scheme: scheme.Scheme,
100-
}).SetupWithManager(mgr)
105+
Client: k8sManager.GetClient(),
106+
Scheme: k8sManager.GetScheme(),
107+
}).SetupWithManager(k8sManager)
101108
Expect(err).ToNot(HaveOccurred())
102109

103110
err = (&NodeRemediationTemplateReconciler{
104-
Client: mgr.GetClient(),
105-
Scheme: scheme.Scheme,
106-
}).SetupWithManager(mgr)
111+
Client: k8sManager.GetClient(),
112+
Scheme: k8sManager.GetScheme(),
113+
}).SetupWithManager(k8sManager)
107114
Expect(err).ToNot(HaveOccurred())
108115

109116
go func() {
110-
err = mgr.Start(context.Background())
117+
defer GinkgoRecover()
118+
err = k8sManager.Start(ctx)
119+
Expect(err).ToNot(HaveOccurred(), "failed to run manager")
111120
}()
112-
Expect(err).ToNot(HaveOccurred())
113121

114122
Eventually(func() bool {
115123
nodeList := &corev1.NodeList{}
116-
Expect(k8sClient.List(context.Background(), nodeList)).NotTo(HaveOccurred())
124+
Expect(k8sClient.List(ctx, nodeList)).NotTo(HaveOccurred())
117125
for _, node := range nodeList.Items {
118126
for _, c := range node.Status.Conditions {
119127
if c.Type == corev1.NodeReady && c.Status == corev1.ConditionFalse {
@@ -126,6 +134,7 @@ var _ = BeforeSuite(func() {
126134
})
127135

128136
var _ = AfterSuite(func() {
137+
cancel()
129138
By("tearing down the test environment")
130139
err := testEnv.Stop()
131140
Expect(err).NotTo(HaveOccurred())

go.mod

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
module github.com/pfnet-research/node-operation-controller
22

3-
go 1.19
3+
go 1.22
44

55
require (
6-
github.com/google/go-cmp v0.5.9
7-
github.com/onsi/ginkgo/v2 v2.6.1
8-
github.com/onsi/gomega v1.24.1
9-
github.com/stretchr/testify v1.8.0
10-
k8s.io/api v0.26.1
11-
k8s.io/apimachinery v0.26.1
12-
k8s.io/client-go v0.26.1
13-
sigs.k8s.io/controller-runtime v0.14.1
6+
github.com/google/go-cmp v0.6.0
7+
github.com/onsi/ginkgo/v2 v2.15.0
8+
github.com/onsi/gomega v1.31.1
9+
github.com/stretchr/testify v1.8.4
10+
k8s.io/api v0.29.2
11+
k8s.io/apimachinery v0.29.2
12+
k8s.io/client-go v0.29.2
13+
sigs.k8s.io/controller-runtime v0.17.2
1414
)
1515

1616
require (

0 commit comments

Comments
 (0)