Skip to content

Commit ea0b2e5

Browse files
authored
Merge pull request #1006 from dhaiducek/update-description-handling
✨ Handle word boundaries and add ellipsis for `MaxDescLen`
2 parents e92e85d + e42b1a2 commit ea0b2e5

File tree

5 files changed

+82
-7
lines changed

5 files changed

+82
-7
lines changed

pkg/crd/desc_visitor.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func TruncateDescription(schema *apiext.JSONSchemaProps, maxLen int) {
3333
// descVisitor recursively visits all fields in the schema and truncates the
3434
// description of the fields to specified maxLen.
3535
type descVisitor struct {
36-
// maxLen is the maximum allowed length for decription of a field
36+
// maxLen is the maximum allowed length for description of a field
3737
maxLen int
3838
}
3939

@@ -60,19 +60,31 @@ func (v descVisitor) Visit(schema *apiext.JSONSchemaProps) SchemaVisitor {
6060
// exceeds maxLen because it tries to chop off the desc at the closest sentence
6161
// boundary to avoid incomplete sentences.
6262
func truncateString(desc string, maxLen int) string {
63+
if len(desc) <= maxLen {
64+
return desc
65+
}
66+
6367
desc = desc[0:maxLen]
6468

6569
// Trying to chop off at closest sentence boundary.
6670
if n := strings.LastIndexFunc(desc, isSentenceTerminal); n > 0 {
6771
return desc[0 : n+1]
6872
}
69-
// TODO(droot): Improve the logic to chop off at closest word boundary
70-
// or add elipses (...) to indicate that it's chopped incase no closest
71-
// sentence found within maxLen.
72-
return desc
73+
74+
// Trying to chop off at closest word boundary (i.e. whitespace).
75+
if n := strings.LastIndexFunc(desc, isWhiteSpace); n > 0 {
76+
return desc[0 : n] + "..."
77+
}
78+
79+
return desc[0:maxLen] + "..."
7380
}
7481

7582
// helper function to determine if given rune is a sentence terminal or not.
7683
func isSentenceTerminal(r rune) bool {
7784
return unicode.Is(unicode.STerm, r)
7885
}
86+
87+
// helper function to determine if given rune is whitespace or not.
88+
func isWhiteSpace(r rune) bool {
89+
return unicode.Is(unicode.White_Space, r)
90+
}

pkg/crd/desc_visitor_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ var _ = Describe("TruncateDescription", func() {
7575
}
7676
crd.TruncateDescription(schema, len(schema.Description)-2)
7777
Expect(schema).To(Equal(&apiext.JSONSchemaProps{
78-
Description: `This is top level description of the root obje`,
78+
Description: `This is top level description of the root...`,
7979
}))
8080
})
8181
})

pkg/crd/gen.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ type Generator struct {
9393
// This value can only be specified for CustomResourceDefinitions that were created with
9494
// `apiextensions.k8s.io/v1beta1`.
9595
//
96-
// The field can be set for compatiblity reasons, although strongly discouraged, resource
96+
// The field can be set for compatibility reasons, although strongly discouraged, resource
9797
// authors should move to a structural OpenAPI schema instead.
9898
//
9999
// See https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#field-pruning

pkg/crd/gen_integration_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,24 @@ var _ = Describe("CRD Generation proper defaulting", func() {
156156
By("searching preserveUnknownFields")
157157
Expect(out.buf.String()).NotTo(ContainSubstring("preserveUnknownFields"))
158158
})
159+
160+
It("should truncate CRD descriptions", func() {
161+
By("calling Generate")
162+
var fifty int = 50
163+
gen := &crd.Generator{
164+
CRDVersions: []string{"v1"},
165+
MaxDescLen: &fifty,
166+
}
167+
Expect(gen.Generate(ctx)).NotTo(HaveOccurred())
168+
169+
By("loading the desired YAML")
170+
expectedFile, err := os.ReadFile(filepath.Join(genDir, "bar.example.com_foos_maxdesclen.yaml"))
171+
Expect(err).NotTo(HaveOccurred())
172+
expectedFile = fixAnnotations(expectedFile)
173+
174+
By("comparing the two")
175+
Expect(out.buf.String()).To(Equal(string(expectedFile)), cmp.Diff(out.buf.String(), string(expectedFile)))
176+
})
159177
})
160178

161179
// fixAnnotations fixes the attribution annotation for tests.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: (devel)
7+
name: foos.bar.example.com
8+
spec:
9+
group: bar.example.com
10+
names:
11+
kind: Foo
12+
listKind: FooList
13+
plural: foos
14+
singular: foo
15+
scope: Namespaced
16+
versions:
17+
- name: foo
18+
schema:
19+
openAPIV3Schema:
20+
properties:
21+
apiVersion:
22+
description: APIVersion defines the versioned schema of this...
23+
type: string
24+
kind:
25+
description: Kind is a string value representing the REST...
26+
type: string
27+
metadata:
28+
type: object
29+
spec:
30+
description: Spec comments SHOULD appear in the CRD spec
31+
properties:
32+
defaultedString:
33+
default: fooDefaultString
34+
description: This tests that defaulted fields are stripped for...
35+
example: fooExampleString
36+
type: string
37+
required:
38+
- defaultedString
39+
type: object
40+
status:
41+
description: Status comments SHOULD appear in the CRD spec
42+
type: object
43+
type: object
44+
served: true
45+
storage: true

0 commit comments

Comments
 (0)