Skip to content

Commit 07c86c2

Browse files
committed
add kube-api-linter and resolve API issues
Add kube-api-linter to `make lint`. kube-api-linter is based on golangci-lint v2, so it is upgraded to the latest version. kube-api-linter could be integrated with COSI CI in many ways. After experimentation, it is fastest to run it as a standalone install rather than build it each time `make lint` is run. Signed-off-by: Blaine Gardner <[email protected]>
1 parent dd3910f commit 07c86c2

File tree

7 files changed

+119
-87
lines changed

7 files changed

+119
-87
lines changed

.golangci.yaml

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
1+
version: "2"
2+
13
run:
24
timeout: 5m
35
allow-parallel-runners: true
46

5-
issues:
6-
# don't skip warning about doc comments
7-
# don't exclude the default set of lint
8-
exclude-use-default: false
9-
# restore some of the defaults
10-
# (fill in the rest as needed)
11-
exclude-rules:
12-
- path: "apis/*"
13-
linters:
14-
- lll
15-
- path: "internal/*"
16-
linters:
17-
- dupl
18-
- lll
19-
- path: "_test.go"
20-
linters:
21-
- goconst
22-
237
linters:
24-
disable-all: true
8+
default: none
259
enable:
2610
- copyloopvar
2711
- dupl
@@ -31,7 +15,6 @@ linters:
3115
- gocyclo
3216
- gofmt
3317
- goimports
34-
- gosimple
3518
- govet
3619
- ineffassign
3720
- lll
@@ -40,12 +23,32 @@ linters:
4023
- prealloc
4124
- revive
4225
- staticcheck
43-
- typecheck
4426
- unconvert
4527
- unparam
4628
- unused
4729

48-
linters-settings:
49-
revive:
30+
settings:
31+
revive:
32+
rules:
33+
- name: comment-spacings
34+
35+
exclusions:
36+
generated: lax
5037
rules:
51-
- name: comment-spacings
38+
- linters:
39+
- lll
40+
path: apis/*
41+
- linters:
42+
- dupl
43+
- lll
44+
path: internal/*
45+
- linters:
46+
- goconst
47+
path: _test.go
48+
49+
formatters:
50+
enable:
51+
- gofmt
52+
- goimports
53+
exclusions:
54+
generated: lax

Makefile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ export
5656
all: prebuild build ## Build all container images, plus their prerequisites (faster with 'make -j')
5757

5858
.PHONY: lint
59-
lint: golangci-lint.client golangci-lint.controller golangci-lint.sidecar spell-lint dockerfiles-lint ## Run all linters (suggest `make -k`)
59+
lint: golangci-lint.client golangci-lint.controller golangci-lint.sidecar kubeapi-lint spell-lint dockerfiles-lint ## Run all linters (suggest `make -k`)
6060
golangci-lint.%: golangci-lint
6161
cd $* && $(GOLANGCI_LINT) run $(GOLANGCI_LINT_RUN_OPTS) --config $(CURDIR)/.golangci.yaml --new
62+
kubeapi-lint: kube-api-linter
63+
cd client/apis && $(KUBEAPI_LINT) run --config $(CURDIR)/client/.kubeapilint.yaml
6264
spell-lint:
6365
git ls-files | grep -v -e CHANGELOG -e go.mod -e go.sum -e vendor | xargs $(SPELL_LINT) -i "Creater,creater,ect" -error -o stderr
6466
dockerfiles-lint:
@@ -192,6 +194,7 @@ CRD_REF_DOCS ?= $(TOOLBIN)/crd-ref-docs
192194
CTLPTL ?= $(TOOLBIN)/ctlptl
193195
GOLANGCI_LINT ?= $(TOOLBIN)/golangci-lint
194196
KIND ?= $(TOOLBIN)/kind
197+
KUBEAPI_LINT ?= $(TOOLBIN)/golangci-lint-kube-api-linter
195198
KUSTOMIZE ?= $(TOOLBIN)/kustomize
196199
MDBOOK ?= $(TOOLBIN)/mdbook
197200
SPELL_LINT ?= $(TOOLBIN)/spell-lint
@@ -201,8 +204,9 @@ CHAINSAW_VERSION ?= v0.2.12
201204
CONTROLLER_TOOLS_VERSION ?= v0.19.0
202205
CRD_REF_DOCS_VERSION ?= v0.2.0
203206
CTLPTL_VERSION ?= v0.8.39
204-
GOLANGCI_LINT_VERSION ?= v1.64.7
207+
GOLANGCI_LINT_VERSION ?= v2.7.2
205208
KIND_VERSION ?= v0.27.0
209+
KUBEAPI_LINT_VERSION ?= v0.0.0-20251208100930-d3015c953951
206210
KUSTOMIZE_VERSION ?= v5.6.0
207211
MDBOOK_VERSION ?= v0.4.47
208212
SPELL_LINT_VERSION ?= v0.6.0
@@ -238,6 +242,11 @@ kind: $(KIND)-$(KIND_VERSION)
238242
$(KIND)-$(KIND_VERSION): $(TOOLBIN)
239243
$(call go-install-tool,$(KIND),sigs.k8s.io/kind,$(KIND_VERSION))
240244

245+
.PHONY: kube-api-linter
246+
kube-api-linter: $(KUBEAPI_LINT)-$(KUBEAPI_LINT_VERSION)
247+
$(KUBEAPI_LINT)-$(KUBEAPI_LINT_VERSION): $(TOOLBIN)
248+
$(call go-install-tool,$(KUBEAPI_LINT),sigs.k8s.io/kube-api-linter/cmd/golangci-lint-kube-api-linter,$(KUBEAPI_LINT_VERSION))
249+
241250
.PHONY: kustomize
242251
kustomize: $(KUSTOMIZE)-$(KUSTOMIZE_VERSION)
243252
$(KUSTOMIZE)-$(KUSTOMIZE_VERSION): $(TOOLBIN)

client/.kubeapilint.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# This is a golangci-lint configuration file specifically for kube-api-linter.
2+
3+
version: "2"
4+
5+
linters:
6+
default: none
7+
enable:
8+
- kubeapilinter
9+
10+
settings:
11+
custom:
12+
kubeapilinter:
13+
type: module
14+
description: Kube API Linter lints Kube like APIs based on API conventions and best practices.
15+
settings:
16+
linters: {}
17+
lintersConfig:
18+
optionalfields:
19+
pointers:
20+
preference: WhenRequired

client/apis/objectstorage/v1alpha2/bucket_types.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,23 @@ const (
3737
)
3838

3939
// BucketSpec defines the desired state of Bucket
40-
// +kubebuilder:validation:XValidation:message="parameters map is immutable",rule="has(oldSelf.parameters) == has(self.parameters)"
41-
// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="has(oldSelf.protocols) == has(self.protocols)"
42-
// +kubebuilder:validation:XValidation:message="existingBucketID is immutable",rule="has(oldSelf.existingBucketID) == has(self.existingBucketID)"
40+
// +kubebuilder:validation:XValidation:message="parameters map cannot be added or removed after creation",rule="has(oldSelf.parameters) == has(self.parameters)"
41+
// +kubebuilder:validation:XValidation:message="protocols list cannot be added or removed after creation",rule="has(oldSelf.protocols) == has(self.protocols)"
42+
// +kubebuilder:validation:XValidation:message="existingBucketID cannot be added or removed after creation",rule="has(oldSelf.existingBucketID) == has(self.existingBucketID)"
4343
type BucketSpec struct {
4444
// driverName is the name of the driver that fulfills requests for this Bucket.
4545
// +required
4646
// +kubebuilder:validation:MinLength=1
4747
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="self == oldSelf"
48-
DriverName string `json:"driverName"`
48+
DriverName string `json:"driverName,omitempty"`
4949

5050
// deletionPolicy determines whether a Bucket should be deleted when its bound BucketClaim is
5151
// deleted. This is mutable to allow Admins to change the policy after creation.
5252
// Possible values:
5353
// - Retain: keep both the Bucket object and the backend bucket
5454
// - Delete: delete both the Bucket object and the backend bucket
5555
// +required
56-
DeletionPolicy BucketDeletionPolicy `json:"deletionPolicy"`
56+
DeletionPolicy BucketDeletionPolicy `json:"deletionPolicy,omitempty"`
5757

5858
// parameters is an opaque map of driver-specific configuration items passed to the driver that
5959
// fulfills requests for this Bucket.
@@ -72,68 +72,70 @@ type BucketSpec struct {
7272
// For statically-provisioned buckets, set the namespace and name of the BucketClaim that is
7373
// allowed to bind to this Bucket.
7474
// +required
75-
BucketClaimRef BucketClaimReference `json:"bucketClaim"`
75+
BucketClaimRef BucketClaimReference `json:"bucketClaim,omitzero"`
7676

7777
// existingBucketID is the unique identifier for an existing backend bucket known to the driver.
7878
// Use driver documentation to determine how to set this value.
7979
// This field is used only for Bucket static provisioning.
8080
// This field will be empty when the Bucket is dynamically provisioned from a BucketClaim.
8181
// +optional
82+
// +kubebuilder:validation:MinLength=1
8283
// +kubebuilder:validation:XValidation:message="existingBucketID is immutable",rule="self == oldSelf"
8384
ExistingBucketID string `json:"existingBucketID,omitempty"`
8485
}
8586

8687
// BucketClaimReference is a reference to a BucketClaim object.
87-
// +kubebuilder:validation:XValidation:message="namespace is immutable once set",rule="!has(oldSelf.namespace) || has(self.namespace)"
88-
// +kubebuilder:validation:XValidation:message="uid is immutable once set",rule="!has(oldSelf.uid) || has(self.uid)"
88+
// +kubebuilder:validation:XValidation:message="namespace cannot be removed once set",rule="!has(oldSelf.namespace) || has(self.namespace)"
89+
// +kubebuilder:validation:XValidation:message="uid cannot be removed once set",rule="!has(oldSelf.uid) || has(self.uid)"
8990
type BucketClaimReference struct {
9091
// name is the name of the BucketClaim being referenced.
9192
// +required
9293
// +kubebuilder:validation:MinLength=1
9394
// +kubebuilder:validation:MaxLength=253
9495
// +kubebuilder:validation:XValidation:message="name is immutable",rule="self == oldSelf"
95-
Name string `json:"name"`
96+
Name string `json:"name,omitempty"`
9697

9798
// namespace is the namespace of the BucketClaim being referenced.
98-
// If empty, the Kubernetes 'default' namespace is assumed.
99-
// namespace is immutable except to update '' to 'default'.
100-
// +optional
101-
// +kubebuilder:validation:MinLength=0
99+
// +required
100+
// +kubebuilder:validation:MinLength=1
102101
// +kubebuilder:validation:MaxLength=253
103102
// +kubebuilder:validation:XValidation:message="namespace is immutable",rule="(oldSelf == '' && self == 'default') || self == oldSelf"
104-
Namespace string `json:"namespace"`
103+
Namespace string `json:"namespace,omitempty"`
105104

106105
// uid is the UID of the BucketClaim being referenced.
107106
// +optional
108107
// +kubebuilder:validation:XValidation:message="uid is immutable once set",rule="oldSelf == '' || self == oldSelf"
109-
UID types.UID `json:"uid"`
108+
UID types.UID `json:"uid,omitempty"`
110109
}
111110

112111
// BucketStatus defines the observed state of Bucket.
113-
// +kubebuilder:validation:XValidation:message="bucketID is immutable once set",rule="!has(oldSelf.bucketID) || has(self.bucketID)"
114-
// +kubebuilder:validation:XValidation:message="protocols is immutable once set",rule="!has(oldSelf.protocols) || has(self.protocols)"
112+
// +kubebuilder:validation:XValidation:message="bucketID cannot be removed once set",rule="!has(oldSelf.bucketID) || has(self.bucketID)"
113+
// +kubebuilder:validation:XValidation:message="protocols cannot be removed once set",rule="!has(oldSelf.protocols) || has(self.protocols)"
115114
type BucketStatus struct {
116115
// readyToUse indicates that the bucket is ready for consumption by workloads.
117-
ReadyToUse bool `json:"readyToUse"`
116+
// +optional
117+
ReadyToUse bool `json:"readyToUse,omitempty"`
118118

119119
// bucketID is the unique identifier for the backend bucket known to the driver.
120120
// +optional
121+
// +kubebuilder:validation:MinLength=1
121122
// +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="oldSelf == '' || self == oldSelf"
122-
BucketID string `json:"bucketID"`
123+
BucketID string `json:"bucketID,omitempty"`
123124

124125
// protocols is the set of protocols the Bucket reports to support. BucketAccesses can request
125126
// access to this BucketClaim using any of the protocols reported here.
126127
// +optional
127128
// +listType=set
128-
Protocols []ObjectProtocol `json:"protocols"`
129+
Protocols []ObjectProtocol `json:"protocols,omitempty"`
129130

130-
// BucketInfo reported by the driver, rendered in the COSI_<PROTOCOL>_<KEY> format used for the
131-
// BucketAccess Secret. e.g., COSI_S3_ENDPOINT, COSI_AZURE_STORAGE_ACCOUNT.
131+
// bucketInfo contains info about the bucket reported by the driver, rendered in the same
132+
// COSI_<PROTOCOL>_<KEY> format used for the BucketAccess Secret.
133+
// e.g., COSI_S3_ENDPOINT, COSI_AZURE_STORAGE_ACCOUNT.
132134
// This should not contain any sensitive information.
133135
// +optional
134136
BucketInfo map[string]string `json:"bucketInfo,omitempty"`
135137

136-
// Error holds the most recent error message, with a timestamp.
138+
// error holds the most recent error message, with a timestamp.
137139
// This is cleared when provisioning is successful.
138140
// +optional
139141
Error *TimestampedError `json:"error,omitempty"`
@@ -154,11 +156,11 @@ type Bucket struct {
154156

155157
// spec defines the desired state of Bucket
156158
// +required
157-
Spec BucketSpec `json:"spec"`
159+
Spec BucketSpec `json:"spec,omitzero"`
158160

159161
// status defines the observed state of Bucket
160162
// +optional
161-
Status BucketStatus `json:"status,omitempty,omitzero"`
163+
Status BucketStatus `json:"status,omitzero"`
162164
}
163165

164166
// +kubebuilder:object:root=true

client/config/crd/objectstorage.k8s.io_buckets.yaml

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,10 @@ spec:
5555
- message: name is immutable
5656
rule: self == oldSelf
5757
namespace:
58-
description: |-
59-
namespace is the namespace of the BucketClaim being referenced.
60-
If empty, the Kubernetes 'default' namespace is assumed.
61-
namespace is immutable except to update '' to 'default'.
58+
description: namespace is the namespace of the BucketClaim being
59+
referenced.
6260
maxLength: 253
63-
minLength: 0
61+
minLength: 1
6462
type: string
6563
x-kubernetes-validations:
6664
- message: namespace is immutable
@@ -73,11 +71,12 @@ spec:
7371
rule: oldSelf == '' || self == oldSelf
7472
required:
7573
- name
74+
- namespace
7675
type: object
7776
x-kubernetes-validations:
78-
- message: namespace is immutable once set
77+
- message: namespace cannot be removed once set
7978
rule: '!has(oldSelf.namespace) || has(self.namespace)'
80-
- message: uid is immutable once set
79+
- message: uid cannot be removed once set
8180
rule: '!has(oldSelf.uid) || has(self.uid)'
8281
deletionPolicy:
8382
description: |-
@@ -104,6 +103,7 @@ spec:
104103
Use driver documentation to determine how to set this value.
105104
This field is used only for Bucket static provisioning.
106105
This field will be empty when the Bucket is dynamically provisioned from a BucketClaim.
106+
minLength: 1
107107
type: string
108108
x-kubernetes-validations:
109109
- message: existingBucketID is immutable
@@ -140,11 +140,11 @@ spec:
140140
- driverName
141141
type: object
142142
x-kubernetes-validations:
143-
- message: parameters map is immutable
143+
- message: parameters map cannot be added or removed after creation
144144
rule: has(oldSelf.parameters) == has(self.parameters)
145-
- message: protocols list is immutable
145+
- message: protocols list cannot be added or removed after creation
146146
rule: has(oldSelf.protocols) == has(self.protocols)
147-
- message: existingBucketID is immutable
147+
- message: existingBucketID cannot be added or removed after creation
148148
rule: has(oldSelf.existingBucketID) == has(self.existingBucketID)
149149
status:
150150
description: status defines the observed state of Bucket
@@ -196,13 +196,11 @@ spec:
196196
description: readyToUse indicates that the bucket is ready for consumption
197197
by workloads.
198198
type: boolean
199-
required:
200-
- readyToUse
201199
type: object
202200
x-kubernetes-validations:
203-
- message: bucketID is immutable once set
201+
- message: bucketID cannot be removed once set
204202
rule: '!has(oldSelf.bucketID) || has(self.bucketID)'
205-
- message: protocols is immutable once set
203+
- message: protocols cannot be removed once set
206204
rule: '!has(oldSelf.protocols) || has(self.protocols)'
207205
required:
208206
- spec

docs/src/api/out.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ _Appears in:_
333333
| Field | Description | Default | Validation |
334334
| --- | --- | --- | --- |
335335
| `name` _string_ | name is the name of the BucketClaim being referenced. | | MaxLength: 253 <br />MinLength: 1 <br /> |
336-
| `namespace` _string_ | namespace is the namespace of the BucketClaim being referenced.<br />If empty, the Kubernetes 'default' namespace is assumed.<br />namespace is immutable except to update '' to 'default'. | | MaxLength: 253 <br />MinLength: 0 <br /> |
336+
| `namespace` _string_ | namespace is the namespace of the BucketClaim being referenced. | | MaxLength: 253 <br />MinLength: 1 <br /> |
337337
| `uid` _[UID](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#uid-types-pkg)_ | uid is the UID of the BucketClaim being referenced. | | |
338338

339339

@@ -495,7 +495,7 @@ _Appears in:_
495495
| `parameters` _object (keys:string, values:string)_ | parameters is an opaque map of driver-specific configuration items passed to the driver that<br />fulfills requests for this Bucket. | | |
496496
| `protocols` _[ObjectProtocol](#objectprotocol) array_ | protocols lists object store protocols that the provisioned Bucket must support.<br />If specified, COSI will verify that each item is advertised as supported by the driver. | | Enum: [S3 Azure GCS] <br /> |
497497
| `bucketClaim` _[BucketClaimReference](#bucketclaimreference)_ | bucketClaim references the BucketClaim that resulted in the creation of this Bucket.<br />For statically-provisioned buckets, set the namespace and name of the BucketClaim that is<br />allowed to bind to this Bucket. | | |
498-
| `existingBucketID` _string_ | existingBucketID is the unique identifier for an existing backend bucket known to the driver.<br />Use driver documentation to determine how to set this value.<br />This field is used only for Bucket static provisioning.<br />This field will be empty when the Bucket is dynamically provisioned from a BucketClaim. | | |
498+
| `existingBucketID` _string_ | existingBucketID is the unique identifier for an existing backend bucket known to the driver.<br />Use driver documentation to determine how to set this value.<br />This field is used only for Bucket static provisioning.<br />This field will be empty when the Bucket is dynamically provisioned from a BucketClaim. | | MinLength: 1 <br /> |
499499

500500

501501
#### BucketStatus

0 commit comments

Comments
 (0)