Skip to content

Commit 338374e

Browse files
authored
support field custom documentation strings (#394)
Adds support for extending the documentation strings for fields and setting docstrings for custom fields. A new `FieldConfig.Documentation` configuration option is now supported. When present, this string *extends* any documentation provided for the existing field by the doc-2.json files. If no such documentation is provided by the existing field OR if the field is a custom field, the `FieldConfig.Documentation` configuration option is used for the field's docstring in the Go type files. Example usage for an existing nested field (from a hypothetical ec2 generator.yaml file). The `LaunchTemplateData.HibernationOptions.Configured` field has a docstring already that contains the following: ``` // If you set this parameter to true, the instance is enabled for hibernation. // // Default: false ``` Setting the `generator.yaml` file to the following: ```yaml resources: LaunchTemplate: fields: LaunchTemplateData.HibernationOptions.Configured: documentation: XXX extended docs XXX ``` would cause the field's Documentation string to look like this: ``` // If you set this parameter to true, the instance is enabled for hibernation. // // Default: false // // XXX extended docs XXX", ``` Issue aws-controllers-k8s/community#1223 Signed-off-by: Jay Pipes <[email protected]>
1 parent 14dcc10 commit 338374e

File tree

5 files changed

+183
-6
lines changed

5 files changed

+183
-6
lines changed

pkg/config/field.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313

1414
package config
1515

16-
import "strings"
16+
import (
17+
"strings"
18+
)
1719

1820
// SourceFieldConfig instructs the code generator how to handle a field in the
1921
// Resource's SpecFields/StatusFields collection that takes its value from an
@@ -390,10 +392,15 @@ type FieldConfig struct {
390392
// TODO(jaypipes,crtbry): Figure out if we can roll the CustomShape stuff
391393
// into this type override...
392394
Type *string `json:"type,omitempty"`
395+
// Documentation is a string that is added *in addition to* any existing
396+
// field documentation derived from the field's doc-2.json contents. For
397+
// custom fields, this allows you to add custom documentation for the
398+
// field.
399+
Documentation *string `json:"documentation,omitempty"`
393400
}
394401

395402
// GetFieldConfigs returns all FieldConfigs for a given resource as a map.
396-
// The map is keyed by the resource's field names after applying renames, if applicable.
403+
// The map is keyed by the resource's field paths
397404
func (c *Config) GetFieldConfigs(resourceName string) map[string]*FieldConfig {
398405
if c == nil {
399406
return map[string]*FieldConfig{}

pkg/model/field.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,65 @@ type Field struct {
6464
MemberFields map[string]*Field
6565
}
6666

67+
// GetDocumentation returns a string containing the field's
68+
// description/docstring. If the field has a ShapeRef that has non-empty
69+
// Documentation AND the field has a Documentation configuration option, then
70+
// the docstring contained in the Documentation configuration option will be
71+
// appended to ShapeRef's docstring following 2 line breaks with Go comment
72+
// line beginnings.
73+
//
74+
// In other words, if there is a field with a ShapeRef that has a Documentation string containing:
75+
//
76+
// "// This field contains the identifier for the cluster
77+
//
78+
// // running the cache services"
79+
//
80+
// and the field has a FieldConfig.Documentation string containing:
81+
//
82+
// "please note that this field is updated on the service
83+
//
84+
// side"
85+
//
86+
// then the string returned from this method will be:
87+
//
88+
// "// This field contains the identifier for the cluster
89+
//
90+
// // running the cache services
91+
// //
92+
// // please note that this field is updated on the service
93+
// // side"
94+
func (f *Field) GetDocumentation() string {
95+
hasShapeDoc := false
96+
var sb strings.Builder
97+
if f.ShapeRef != nil {
98+
if f.ShapeRef.Documentation != "" {
99+
hasShapeDoc = true
100+
sb.WriteString(f.ShapeRef.Documentation)
101+
}
102+
}
103+
if f.FieldConfig != nil {
104+
if f.FieldConfig.Documentation != nil {
105+
if hasShapeDoc {
106+
sb.WriteString("\n//\n")
107+
}
108+
// Strip any leading comment slashes from the config option
109+
// docstring since we'll be automatically adding the Go comment
110+
// slashes to the beginning of each new line
111+
cfgDoc := *f.FieldConfig.Documentation
112+
lines := strings.Split(cfgDoc, "\n")
113+
numLines := len(lines)
114+
for x, line := range lines {
115+
sb.WriteString("// ")
116+
sb.WriteString(strings.TrimLeft(line, "/ "))
117+
if x < (numLines - 1) {
118+
sb.WriteString("\n")
119+
}
120+
}
121+
}
122+
}
123+
return sb.String()
124+
}
125+
67126
// IsRequired checks the FieldConfig for Field and returns if the field is
68127
// marked as required or not.A
69128
//

pkg/model/field_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,51 @@ import (
1414
"github.com/aws-controllers-k8s/code-generator/pkg/testutil"
1515
)
1616

17+
func TestFieldDocumentation(t *testing.T) {
18+
require := require.New(t)
19+
20+
g := testutil.NewModelForServiceWithOptions(t, "ec2",
21+
&testutil.TestingModelOptions{
22+
GeneratorConfigFile: "generator-with-doc-overrides.yaml",
23+
},
24+
)
25+
26+
crds, err := g.GetCRDs()
27+
require.Nil(err)
28+
29+
crd := getCRDByName("LaunchTemplate", crds)
30+
require.NotNil(crd)
31+
32+
specFields := crd.SpecFields
33+
34+
// We have not altered the docstring for LaunchTemplateData from the
35+
// docstring that comes in the doc-2.json file...
36+
ltdField := specFields["LaunchTemplateData"]
37+
require.NotNil(ltdField)
38+
require.NotNil(ltdField.ShapeRef)
39+
40+
require.Equal(
41+
"// The information for the launch template.",
42+
ltdField.GetDocumentation(),
43+
)
44+
45+
// We have added an additional docstring for
46+
// LaunchTemplateData.HibernationOptions.Configured to the docstring that
47+
// comes in the doc-2.json file...
48+
hoField := ltdField.MemberFields["HibernationOptions"]
49+
require.NotNil(hoField)
50+
require.NotNil(hoField.ShapeRef)
51+
hocField := hoField.MemberFields["Configured"]
52+
require.NotNil(hocField)
53+
require.NotNil(hocField.ShapeRef)
54+
55+
require.Equal(
56+
"// If you set this parameter to true, the instance is enabled for hibernation.\n// \n// Default: false\n//\n// XXX extended docs XXX",
57+
hocField.GetDocumentation(),
58+
)
59+
60+
}
61+
1762
func TestMemberFields(t *testing.T) {
1863
assert := assert.New(t)
1964
require := require.New(t)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
ignore:
2+
resource_names:
3+
- AccountAttribute
4+
- CapacityReservation
5+
- CarrierGateway
6+
- ClientVpnEndpoint
7+
- ClientVpnRoute
8+
- CustomerGateway
9+
- DefaultSubnet
10+
- DefaultVpc
11+
- DhcpOptions
12+
- EgressOnlyInternetGateway
13+
- Fleet
14+
- FpgaImage
15+
- Image
16+
- Instance
17+
- InstanceExportTask
18+
- InternetGateway
19+
- KeyPair
20+
- LaunchTemplateVersion
21+
#- LaunchTemplate
22+
- LocalGatewayRouteTableVpcAssociation
23+
- LocalGatewayRoute
24+
- ManagedPrefixList
25+
- NatGateway
26+
- NetworkAclEntry
27+
- NetworkAcl
28+
- NetworkInsightsPath
29+
- NetworkInterfacePermission
30+
- NetworkInterface
31+
- PlacementGroup
32+
- ReservedInstancesListing
33+
- RouteTable
34+
- Route
35+
- SecurityGroup
36+
- Snapshot
37+
- SpotDatafeedSubscription
38+
- Subnet
39+
- TrafficMirrorFilterRule
40+
- TrafficMirrorFilter
41+
- TrafficMirrorSession
42+
- TrafficMirrorTarget
43+
- TransitGatewayConnectPeer
44+
- TransitGatewayConnect
45+
- TransitGatewayMulticastDomain
46+
- TransitGatewayPeeringAttachment
47+
- TransitGatewayPrefixListReference
48+
- TransitGatewayRouteTable
49+
- TransitGatewayRoute
50+
- TransitGatewayVpcAttachment
51+
- TransitGateway
52+
- Volume
53+
- VpcEndpointConnectionNotification
54+
- VpcEndpointServiceConfiguration
55+
- VpcEndpoint
56+
- Vpc
57+
- VpcCidrBlock
58+
- VpcPeeringConnection
59+
- VpnConnectionRoute
60+
- VpnConnection
61+
- VpnGateway
62+
resources:
63+
LaunchTemplate:
64+
fields:
65+
LaunchTemplateData.HibernationOptions.Configured:
66+
documentation: XXX extended docs XXX

templates/apis/crd.go.tpl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import (
1616
{{ .CRD.Documentation }}
1717
type {{ .CRD.Kind }}Spec struct {
1818
{{ range $fieldName, $field := .CRD.SpecFields }}
19-
{{ if and ($field.ShapeRef) ($field.ShapeRef.Documentation) -}}
20-
{{ $field.ShapeRef.Documentation }}
19+
{{ if $field.GetDocumentation -}}
20+
{{ $field.GetDocumentation }}
2121
{{ end -}}
2222
{{- if and ($field.IsRequired) (not $field.HasReference) -}}
2323
// +kubebuilder:validation:Required
@@ -40,8 +40,8 @@ type {{ .CRD.Kind }}Status struct {
4040
// +kubebuilder:validation:Optional
4141
Conditions []*ackv1alpha1.Condition `json:"conditions"`
4242
{{- range $fieldName, $field := .CRD.StatusFields }}
43-
{{- if and ($field.ShapeRef) ($field.ShapeRef.Documentation) }}
44-
{{ $field.ShapeRef.Documentation }}
43+
{{- if $field.GetDocumentation }}
44+
{{ $field.GetDocumentation }}
4545
{{- end }}
4646
// +kubebuilder:validation:Optional
4747
{{ $field.Names.Camel }} {{ $field.GoType }} `json:"{{ $field.Names.CamelLower }},omitempty"`

0 commit comments

Comments
 (0)