Skip to content

Commit 60c2779

Browse files
authored
Add reconciliation status + always update status of managed resources. (#76)
1 parent 7199e52 commit 60c2779

File tree

8 files changed

+114
-78
lines changed

8 files changed

+114
-78
lines changed

.github/workflows/docker.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
cache: false
3939

4040
- name: Lint
41-
uses: golangci/golangci-lint-action@v4
41+
uses: golangci/golangci-lint-action@v5
4242
with:
4343
args: --build-tags integration -p bugs -p unused --timeout=5m
4444

@@ -48,7 +48,12 @@ jobs:
4848
[ "${GITHUB_EVENT_NAME}" == 'release' ] && echo "tag=${GITHUB_REF##*/}" >> $GITHUB_ENV || true
4949
[ "${GITHUB_EVENT_NAME}" == 'push' ] && echo "tag=latest" >> $GITHUB_ENV || true
5050
51-
- name: Build and push image
51+
- name: Test and build
52+
run: |
53+
make test
54+
make
55+
56+
- name: Push image
5257
uses: docker/build-push-action@v5
5358
with:
5459
context: .

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ api/durosv2/*
55
bin/
66
**/*/statik.go
77
.vscode
8+
# Output of the go coverage tool, specifically when used with LiteIDE
9+
*.out

Dockerfile

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,5 @@
1-
# Build the duros-controller binary
2-
FROM golang:1.22 as builder
3-
4-
ENV KUBEBUILDER_DOWNLOAD_URL=https://github.com/kubernetes-sigs/kubebuilder/releases/download
5-
ENV KUBEBUILDER_VER=v3.14.0
6-
RUN set -ex \
7-
&& mkdir -p /usr/local/bin \
8-
&& curl -L ${KUBEBUILDER_DOWNLOAD_URL}/v${KUBEBUILDER_VER}/kubebuilder_linux_amd64 -o /usr/local/bin/kubebuilder \
9-
&& chmod +x /usr/local/bin/kubebuilder
10-
11-
WORKDIR /workspace
12-
# Copy the Go Modules manifests
13-
COPY go.mod go.mod
14-
COPY go.sum go.sum
15-
# cache deps before building and copying source so that we don't need to re-download as much
16-
# and so that source changes don't invalidate our downloaded layer
17-
RUN go mod download
18-
19-
# Copy the go source
20-
COPY .git/ .git/
21-
COPY Makefile Makefile
22-
COPY api/ api/
23-
COPY controllers/ controllers/
24-
COPY hack/ hack/
25-
COPY config/ config/
26-
COPY main.go main.go
27-
28-
# Build
29-
RUN make
30-
31-
# Final Image
321
FROM alpine:3.19
332
WORKDIR /
34-
COPY --from=builder /workspace/bin/duros-controller .
3+
COPY bin/duros-controller .
354
USER 65534
365
ENTRYPOINT ["/duros-controller"]

Makefile

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@ GITVERSION := $(shell git describe --long --all)
1010
BUILDDATE := $(shell date -Iseconds)
1111
VERSION := $(or ${VERSION},devel)
1212

13-
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
14-
ifeq (,$(shell go env GOBIN))
15-
GOBIN=$(shell go env GOPATH)/bin
16-
else
17-
GOBIN=$(shell go env GOBIN)
18-
endif
13+
CONTROLLER_TOOLS_VERSION ?= v0.14.0
14+
LOCALBIN ?= $(shell pwd)/bin
15+
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
1916

2017
all: manager
2118

19+
$(LOCALBIN):
20+
mkdir -p $(LOCALBIN)
21+
2222
# clean generated code
2323
.PHONY: clean
2424
clean:
2525
rm -f api/v1/*pb.go bin/*
2626

2727
# Run tests
2828
test: generate fmt vet manifests
29-
go test ./... -coverprofile cover.out -race -timeout 30s
29+
CGO_ENABLED=1 go test ./... -coverprofile cover.out -race -timeout 30s
3030

3131
# Build manager binary
3232
manager: generate fmt vet
@@ -78,22 +78,11 @@ docker-build: test
7878
docker-push:
7979
docker push ${IMG}
8080

81-
# find or download controller-gen
82-
# download controller-gen if necessary
83-
controller-gen:
84-
ifeq (, $(shell which controller-gen))
85-
@{ \
86-
set -e ;\
87-
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
88-
cd $$CONTROLLER_GEN_TMP_DIR ;\
89-
go mod init tmp ;\
90-
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0 ;\
91-
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
92-
}
93-
CONTROLLER_GEN=$(GOBIN)/controller-gen
94-
else
95-
CONTROLLER_GEN=$(shell which controller-gen)
96-
endif
81+
.PHONY: controller-gen
82+
controller-gen: $(CONTROLLER_GEN)
83+
$(CONTROLLER_GEN): $(LOCALBIN)
84+
test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
85+
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
9786

9887
.PHONY: certs
9988
certs:

api/v1/duros_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ type DurosSpec struct {
5555

5656
// DurosStatus defines the observed state of Duros
5757
type DurosStatus struct {
58+
// ReconcileStatus describes the current status of the reconciliation
59+
ReconcileStatus ReconcileStatus `json:"reconcileStatus" description:"The current status of the reconciliation of this resource"`
5860
// ManagedResourceStatuses contains a list of statuses of resources managed by this controller
5961
ManagedResourceStatuses []ManagedResourceStatus `json:"managedResourceStatuses" description:"A list of managed resource statuses"`
6062
}
@@ -72,6 +74,13 @@ type ManagedResourceStatus struct {
7274
LastUpdateTime metav1.Time `json:"lastUpdateTime" description:"The time when this status was last updated"`
7375
}
7476

77+
type ReconcileStatus struct {
78+
// LastReconcile is the point in time when the last reconciliation took place
79+
LastReconcile *metav1.Time `json:"lastReconcile,omitempty" description:"Timestamp of last reconciliation"`
80+
// Error indicates a reconciliation error that occurred, it's empty when there is no error
81+
Error *string `json:"error,omitempty" description:"If set describes that there is an error during reconciliation"`
82+
}
83+
7584
// HealthState describes the state of a managed resource
7685
type HealthState string
7786

api/v1/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/storage.metal-stack.io_duros.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,22 @@ spec:
109109
- state
110110
type: object
111111
type: array
112+
reconcileStatus:
113+
description: ReconcileStatus describes the current status of the reconciliation
114+
properties:
115+
error:
116+
description: Error indicates a reconciliation error that occurred,
117+
it's empty when there is no error
118+
type: string
119+
lastReconcile:
120+
description: LastReconcile is the point in time when the last
121+
reconciliation took place
122+
format: date-time
123+
type: string
124+
type: object
112125
required:
113126
- managedResourceStatuses
127+
- reconcileStatus
114128
type: object
115129
type: object
116130
served: true

controllers/duros_controller.go

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,36 @@ func (r *DurosReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
8989
return ctrl.Result{}, nil
9090
}
9191

92-
err := validateDuros(duros)
92+
var err error
93+
94+
defer func() {
95+
now := metav1.NewTime(time.Now())
96+
97+
duros.Status.ReconcileStatus = duroscontrollerv1.ReconcileStatus{
98+
LastReconcile: &now,
99+
Error: nil,
100+
}
101+
102+
if err != nil {
103+
msg := err.Error()
104+
duros.Status.ReconcileStatus.Error = &msg
105+
}
106+
107+
r.setManagedResourceStatus(ctx, duros)
108+
109+
if err := r.Status().Update(ctx, duros); err != nil {
110+
log.Error(err, "error updating status of duros resource", "name", duros.Name)
111+
return
112+
}
113+
114+
r.Log.Info("status updated", "name", duros.Name)
115+
}()
116+
117+
err = validateDuros(duros)
93118
if err != nil {
94119
return requeue, err
95120
}
121+
96122
projectID := duros.Spec.MetalProjectID
97123
storageClasses := duros.Spec.StorageClasses
98124

@@ -118,35 +144,38 @@ func (r *DurosReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
118144
return requeue, err
119145
}
120146

121-
err = r.reconcileStatus(ctx, duros)
122-
if err != nil {
123-
return requeue, err
124-
}
125-
126147
return ctrl.Result{
127148
// we requeue in a small interval to ensure resources are recreated quickly
128149
// and status is updated regularly
129150
RequeueAfter: 30 * time.Second,
130151
}, nil
131152
}
132153

133-
func (r *DurosReconciler) reconcileStatus(ctx context.Context, duros *duroscontrollerv1.Duros) error {
154+
func (r *DurosReconciler) setManagedResourceStatus(ctx context.Context, duros *duroscontrollerv1.Duros) {
134155
var (
135156
updateTime = metav1.NewTime(time.Now())
136157
ds = &appsv1.DaemonSet{}
137158
sts = &appsv1.StatefulSet{}
159+
160+
dsState = duroscontrollerv1.HealthStateRunning
161+
dsMsg = "All replicas are ready"
162+
163+
stsState = duroscontrollerv1.HealthStateRunning
164+
stsMsg = "All replicas are ready"
138165
)
139166

140167
err := r.Shoot.Get(ctx, types.NamespacedName{Name: lbCSINodeName, Namespace: namespace}, ds)
141168
if err != nil {
142-
return fmt.Errorf("error getting daemon set: %w", err)
169+
r.Log.Error(err, "error getting daemon set")
170+
dsState = duroscontrollerv1.HealthStateNotRunning
171+
dsMsg = err.Error()
143172
}
144173

145174
dsStatus := duroscontrollerv1.ManagedResourceStatus{
146175
Name: ds.Name,
147176
Group: "DaemonSet", // ds.GetObjectKind().GroupVersionKind().String() --> this does not work :(
148-
State: duroscontrollerv1.HealthStateRunning,
149-
Description: "All replicas are ready",
177+
State: dsState,
178+
Description: dsMsg,
150179
LastUpdateTime: updateTime,
151180
}
152181

@@ -157,14 +186,16 @@ func (r *DurosReconciler) reconcileStatus(ctx context.Context, duros *duroscontr
157186

158187
err = r.Shoot.Get(ctx, types.NamespacedName{Name: lbCSIControllerName, Namespace: namespace}, sts)
159188
if err != nil {
160-
return fmt.Errorf("error getting statefulset: %w", err)
189+
r.Log.Error(err, "error getting stateful set")
190+
stsState = duroscontrollerv1.HealthStateNotRunning
191+
stsMsg = err.Error()
161192
}
162193

163194
stsStatus := duroscontrollerv1.ManagedResourceStatus{
164195
Name: sts.Name,
165196
Group: "StatefulSet", // sts.GetObjectKind().GroupVersionKind().String() --> this does not work :(
166-
State: duroscontrollerv1.HealthStateRunning,
167-
Description: "All replicas are ready",
197+
State: stsState,
198+
Description: stsMsg,
168199
LastUpdateTime: updateTime,
169200
}
170201

@@ -179,14 +210,6 @@ func (r *DurosReconciler) reconcileStatus(ctx context.Context, duros *duroscontr
179210
}
180211

181212
duros.Status.ManagedResourceStatuses = []duroscontrollerv1.ManagedResourceStatus{dsStatus, stsStatus}
182-
err = r.Status().Update(ctx, duros)
183-
if err != nil {
184-
return fmt.Errorf("error updating status: %w", err)
185-
}
186-
187-
r.Log.Info("status updated", "name", duros.Name)
188-
189-
return nil
190213
}
191214

192215
// SetupWithManager boilerplate to setup the Reconciler

0 commit comments

Comments
 (0)