Skip to content

Commit 6bfe3f0

Browse files
committed
Implement ImagePrefetch controller
Signed-off-by: zeroalphat <taichi-takemura@cybozu.co.jp>
1 parent 133561f commit 6bfe3f0

27 files changed

+1877
-86
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build the manager binary
2-
FROM ghcr.io/cybozu/golang:1.23-noble AS builder
2+
FROM ghcr.io/cybozu/golang:1.24-noble AS builder
33
ARG TARGETOS
44
ARG TARGETARCH
55

@@ -11,7 +11,7 @@ RUN go mod download
1111
# Copy the go source
1212
COPY cmd/main.go cmd/main.go
1313
COPY api/ api/
14-
COPY internal/controller/ internal/controller/
14+
COPY internal/ internal/
1515

1616
# Build
1717
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go

Makefile

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
IMG ?= controller:latest
1+
IMG ?= image-prefetch:dev
22
ENVTEST_K8S_VERSION = 1.31.0
33

44
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
@@ -28,6 +28,22 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust
2828
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
2929
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
3030

31+
# refer to https://github.com/statnett/image-scanner-operator/pull/668/files
32+
GO_MODULE = $(shell go list -m)
33+
API_DIRS = $(shell find api -mindepth 1 -type d | sed "s|^|$(shell go list -m)/|" | paste -sd " " )
34+
.PHONY: k8s-client-gen
35+
k8s-client-gen: applyconfiguration-gen models-schema
36+
@echo "generating"
37+
$(MODELS_SCHEMA) > /tmp/schema.json
38+
rm -rf internal/client/applyconfigurations
39+
$(APPLYCONFIGURATION_GEN) \
40+
--go-header-file hack/boilerplate.go.txt \
41+
--output-dir internal/applyconfigurations \
42+
--output-pkg $(GO_MODULE)/internal/applyconfigurations \
43+
--openapi-schema /tmp/schema.json \
44+
$(API_DIRS)
45+
rm -f /tmp/schema.json
46+
3147
.PHONY: fmt
3248
fmt: ## Run go fmt against code.
3349
go fmt ./...
@@ -37,8 +53,8 @@ vet: ## Run go vet against code.
3753
go vet ./...
3854

3955
.PHONY: test
40-
test: manifests generate fmt vet envtest ## Run tests.
41-
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
56+
test: manifests generate fmt vet envtest ginkgo ## Run tests.
57+
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" $(GINKGO) run --skip-file e2e.* -r --coverprofile cover.out
4258

4359
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
4460
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
@@ -111,12 +127,18 @@ KUSTOMIZE ?= $(LOCALBIN)/kustomize
111127
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
112128
ENVTEST ?= $(LOCALBIN)/setup-envtest
113129
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
130+
GINKGO = $(LOCALBIN)/ginkgo
131+
APPLYCONFIGURATION_GEN = $(LOCALBIN)/applyconfiguration-gen
132+
MODELS_SCHEMA = $(LOCALBIN)/models-schema
114133

115134
## Tool Versions
116135
KUSTOMIZE_VERSION ?= v5.6.0
117136
CONTROLLER_TOOLS_VERSION ?= v0.17.2
118137
ENVTEST_VERSION ?= release-0.20
119138
GOLANGCI_LINT_VERSION ?= v1.64.5
139+
GINKGO_VERSION ?= v2.1.4
140+
CODE_GENERATOR_VERSION ?= v0.31.1
141+
MODELS_SCHEMA_VERSION ?= v1.31.1
120142

121143
.PHONY: kustomize
122144
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
@@ -138,6 +160,26 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
138160
$(GOLANGCI_LINT): $(LOCALBIN)
139161
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
140162

163+
.PHONY: ginkgo
164+
ginkgo: $(GINKGO) ## Download ginkgo locally if necessary.
165+
$(GINKGO): $(LOCALBIN)
166+
$(call go-install-tool,$(GINKGO),github.com/onsi/ginkgo/v2/ginkgo,$(GINKGO_VERSION))
167+
168+
.PHONY: models-schema ## Download models-schema locally if necessary.
169+
models-schema: $(LOCALBIN)
170+
test -s $(LOCALBIN)/models-schema || \
171+
( \
172+
mkdir -p /tmp/work-models-schema/pkg/generated/openapi/cmd/models-schema && \
173+
curl -sSfL https://github.com/kubernetes/kubernetes/archive/$(MODELS_SCHEMA_VERSION).tar.gz | tar -C /tmp/work-models-schema -xzf - --strip-components=1 &&\
174+
cd /tmp/work-models-schema/pkg/generated/openapi/cmd/models-schema &&\
175+
GOBIN=$(LOCALBIN) go install \
176+
)
177+
178+
.PHONY: applyconfiguration-gen ## Download applyconfiguration-gen locally if necessary.
179+
applyconfiguration-gen: $(APPLYCONFIGURATION_GEN) ## Download applyconfiguration-gen locally if necessary.
180+
$(APPLYCONFIGURATION_GEN): $(LOCALBIN)
181+
$(call go-install-tool,$(APPLYCONFIGURATION_GEN),k8s.io/code-generator/cmd/applyconfiguration-gen,$(CODE_GENERATOR_VERSION))
182+
141183
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
142184
# $1 - target path with name of binary
143185
# $2 - package url which can be installed

api/v1/doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// +groupName=ofen.cybozu.io
2+
package v1

api/v1/groupversion_info.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import (
1010

1111
var (
1212
// GroupVersion is group version used to register these objects
13-
GroupVersion = schema.GroupVersion{Group: "ofen.cybozu.io", Version: "v1"}
13+
SchemeGroupVersion = schema.GroupVersion{Group: "ofen.cybozu.io", Version: "v1"}
1414

1515
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
16-
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
16+
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
1717

1818
// AddToScheme adds the types in this group-version to the given scheme.
1919
AddToScheme = SchemeBuilder.AddToScheme

api/v1/imageprefetch_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ type ImagePrefetchStatus struct {
5454
// +optional
5555
// +kubebuilder:default:=0
5656
ImagePullFailedNodes int `json:"imagePullFailedNodes,omitempty"`
57+
58+
// SelectedNodes represents the nodes that have been selected to download the images
59+
// +optional
60+
SelectedNodes []string `json:"selectedNodes,omitempty"`
5761
}
5862

5963
const (

api/v1/nodeimageset_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ const (
8080
// +kubebuilder:object:root=true
8181
// +kubebuilder:subresource:status
8282
// +kubebuilder:resource:scope=Cluster
83+
// +genclient
84+
// +genclient:nonNamespaced
8385

8486
// NodeImageSet is the Schema for the nodeimagesets API
8587
type NodeImageSet struct {

api/v1/zz_generated.deepcopy.go

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

cmd/main.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func main() {
4040
var probeAddr string
4141
var secureMetrics bool
4242
var enableHTTP2 bool
43+
var imagePullNodeLimit int
4344
var tlsOpts []func(*tls.Config)
4445
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
4546
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
@@ -51,6 +52,8 @@ func main() {
5152
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
5253
flag.BoolVar(&enableHTTP2, "enable-http2", false,
5354
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
55+
flag.IntVar(&imagePullNodeLimit, "image-pull-node-limit", 1,
56+
"The maximum number of nodes that can pull images concurrently.")
5457
opts := zap.Options{
5558
Development: true,
5659
}
@@ -127,8 +130,9 @@ func main() {
127130
}
128131

129132
if err = (&controller.ImagePrefetchReconciler{
130-
Client: mgr.GetClient(),
131-
Scheme: mgr.GetScheme(),
133+
Client: mgr.GetClient(),
134+
Scheme: mgr.GetScheme(),
135+
ImagePullNodeLimit: imagePullNodeLimit,
132136
}).SetupWithManager(mgr); err != nil {
133137
setupLog.Error(err, "unable to create controller", "controller", "ImagePrefetch")
134138
os.Exit(1)

config/crd/bases/ofen.cybozu.io_imageprefetches.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ spec:
166166
description: The generation observed by the controller.
167167
format: int64
168168
type: integer
169+
selectedNodes:
170+
description: SelectedNodes represents the nodes that have been selected
171+
to download the images
172+
items:
173+
type: string
174+
type: array
169175
type: object
170176
type: object
171177
served: true

config/manager/kustomization.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
resources:
22
- manager.yaml
3+
apiVersion: kustomize.config.k8s.io/v1beta1
4+
kind: Kustomization
5+
images:
6+
- name: controller
7+
newName: image-prefetch
8+
newTag: dev

0 commit comments

Comments
 (0)