You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/content/docs/contributor-docs/code-generator-config.md
+39-39Lines changed: 39 additions & 39 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -169,7 +169,7 @@ pkg/
169
169
170
170
Note the new files under `pkg/resource/repository/`, `apis/v1alpha1/repository.go` and `config/crd/bases/`. These files represent the Go type for the generated `Repository` custom resource definition (CRD), the resource manager package and the YAML representation for the CRD, respectively.
171
171
172
-
## Renaming things
172
+
## `renames`: Renaming things
173
173
174
174
Why might we want to rename fields or resources? Generally, there are two reasons for this:
175
175
- reducing stutter in the input shape
@@ -515,7 +515,7 @@ The second reason we might need to rename a field is when the same field goes by
515
515
[**_TODO_** this needs a concrete example of renaming with both `input_fields` and `output_fields`]
516
516
517
517
518
-
## Ignoring things
518
+
## `ignore`: Ignoring things
519
519
520
520
Sometimes you want to instruct the code generator to simply ignore a particular API Operation, or a particular field in an API Shape. See [here](https://github.com/aws-controllers-k8s/s3-controller/pull/89) for a real world motivating example of such a need.
521
521
@@ -544,7 +544,7 @@ When you specify a field path in `ignore.field_paths`, the code generator will s
544
544
545
545
*Most* resources in AWS service APIs can have one or more tags associated with them. Tags are *typically* simple string key/value pairs; however, the representation of tags across different AWS service APIs is not consistent. Some APIs use a `map[string]string` to represent tags. Others use a `[]struct{}` where the struct has a `Key` and a `Value` field. Others use more complex structures.
546
546
547
-
### Telling ACK code generator that a resource does not support tags
547
+
### `tags.ignore`: Telling ACK code generator that a resource does not support tags
548
548
549
549
There are some API resources that *do not* support tags at all, and we want a way to skip the generation of code that handles tagging for those resources. By default, for all resources, ACK generates some code that handles conversion between the ACK standard representation of tags (i.e., `map[string]string`) and the AWS service-specific representation of tags (e.g., `[]struct{}`, etc).
550
550
@@ -593,13 +593,13 @@ resources:
593
593
594
594
## Resource configuration
595
595
596
-
### Understanding resourceidentifying fields
596
+
### Understanding resource-identifying fields
597
597
598
598
All resources in the AWS world have one or more fields that serve as primary key identifiers. Most people are familiar with the `ARN` fields that most modern AWS resources have. However, the `ARN` field is not the only field that can serve as a primary key for a resource. ACK's code generator reads an API model file and attempts to determine which fields on a resource can be used to uniquely identify that resource. Sometimes, though, the code generator needs to be instructed which field or fields comprise this primary key. [See below](#Field-level-configuration-of-identifying-fields) for an example from ECR's `PullThroughCacheRule`.
599
599
600
600
There are resource-level and field-level configuration options that inform the code generator about identifying fields.
601
601
602
-
#### Resource-level configuration of identifying fields
602
+
#### `is_arn_primary_key`: Resource-level configuration of identifying fields
603
603
604
604
The `resources[$resource].is_arn_primary_key` configuration option is a boolean, defaulting to `false` that instructs the code generator to use the `ARN` field when calling the "ReadOne" (i.e., "Describe" or "Get") operation for that resource. When `false`, the code generator will look for "identifier fields" with field names such as `ID` or `Name` (along with variants that include the resource name as a prefix, e.g., "BucketName").
605
605
@@ -613,7 +613,7 @@ resources:
613
613
614
614
*[NOTE(jaypipes): Probably want to reevaluate this particular config option and use the field-centric is_primary_key option instead...]*
615
615
616
-
#### Field-level configuration of identifying fields
616
+
#### `is_primary_key`: Field-level configuration of identifying fields
617
617
618
618
Sometimes a resource's primary key field is non-obvious (like `Name` or `ID`). Use the `resources[$resource]fields[$field].is_primary_key` configuration option to tell the code generator about these fields.
619
619
@@ -629,7 +629,7 @@ resources:
629
629
630
630
*[NOTE(jljaco): If we discard `is_arn_primary_key` in favor of only `is_primary_key`, this sub-section should be moved into the `Field Configuration` section]*
631
631
632
-
### Correcting exception codes
632
+
### `exceptions`: Correcting exception codes
633
633
634
634
An ACK controller needs to understand which HTTP exception code means "this resource was not found"; otherwise, the controller's logic that determines whether to create or update a resource falls apart.
635
635
@@ -652,7 +652,7 @@ resources:
652
652
653
653
This configuration instructs the code generator to [produce code](https://github.com/aws-controllers-k8s/dynamodb-controller/blob/eb1405d3d10050c8a866dc0e2dc0ec72c8213886/pkg/resource/table/sdk.go#L79-L84) that looks for `ResourceNotFoundException` in the error response of the API call and interprets it properly as a `404` or "resource not found" error.
654
654
655
-
#### Specifying terminal codes to indicate terminal state
655
+
#### `terminal_codes`: Specifying terminal codes to indicate terminal state
656
656
657
657
An `ACK.Terminal``Condition` is placed on a custom resource (inside of its `Status`) when the controller realizes that, without the user changing the resource's `Spec`, the resource will not be able to be reconciled (i.e., the desired state will never match the actual state).
658
658
@@ -681,7 +681,7 @@ resources:
681
681
- StorageQuotaExceeded
682
682
```
683
683
684
-
### Controlling reconciliation and requeue logic
684
+
### `reconcile`: Controlling reconciliation and requeue logic
685
685
686
686
By default, an ACK controller will requeue a resource for future reconciliation only when the resource is in some transitional state.
687
687
@@ -714,7 +714,7 @@ When `ack-generate` first [infers the definition of a resource][api-inference] f
### Manually marking a field as belonging to the resource `Status` struct
717
+
### `is_read_only`: Manually marking a field as belonging to the resource `Status` struct
718
718
719
719
During API inference, `ack-generate` automatically determines which fields belong in the custom resource definition's `Spec` or `Status` struct. Fields that can be modified by the user go in the `Spec` and fields that cannot be modified go in the `Status`.
720
720
@@ -732,7 +732,7 @@ resources:
732
732
733
733
Typically, you will see this configuration option used for fields that have two different Go types representing the modifiable version of the field and the non-modifiable version of the field (as is the case for a Lambda Function's Layers information) or when you need to create a custom field.
734
734
735
-
### Marking a field as required
735
+
### `is_required`: Marking a field as required
736
736
737
737
If an AWS API model file marks a particular member field as required, `ack-generate` will usually infer that the associated custom resource field is required. Sometimes, however, you may want to override whether or not a field should be required. Use the `resources[$resource].fields[$field].is_required` configuration option to do so.
738
738
@@ -750,7 +750,7 @@ resources:
750
750
is_required: false
751
751
```
752
752
753
-
### Controlling a field's Go type
753
+
### `type`: controlling a field's Go type
754
754
755
755
Use the `resources[$resource].fields[$field].type` configuration option to override a field's Go type. You will typically use this configuration option for custom fields that are not inferred by `ack-generate` by looking at the AWS API model definition.
756
756
@@ -767,11 +767,11 @@ resources:
767
767
type: "[]*string"
768
768
```
769
769
770
-
### Controlling how a field's values are compared
770
+
### `compare`: Controlling how a field's values are compared
771
771
772
772
Use the `resources[$resource].fields[$field].compare` configuration option to control how the value of a field is compared between two resources. This configuration option has two boolean subfields, `is_ignored` and `nil_equals_zero_value` (TODO(jljaco): `nil_equals_zero_value`not yet implemented or used).
773
773
774
-
#### Marking a field as ignored
774
+
#### `is_ignored`: marking a field as ignored
775
775
776
776
Use the `is_ignored` subfield to instruct the code generator to exclude this particular field from automatic value comparisons when building the `Delta` struct that compares two resources.
777
777
@@ -788,7 +788,7 @@ Typically, you will want to mark a field as ignored for comparison operations be
788
788
is_ignored: true
789
789
```
790
790
791
-
### Mutable vs. immutable fields
791
+
### `is_immutable`: Mutable vs. immutable fields
792
792
793
793
Use the `resources[$resource].fields[$field].is_immutable` configuration option to mark a field as immutable -- meaning the user cannot update the field after initially setting its value.
794
794
@@ -803,7 +803,7 @@ resources:
803
803
is_immutable: true
804
804
```
805
805
806
-
In the case of an DBInstance resource, once the AvailabilityZone field is set by the user, it cannot be modified.
806
+
In the case of a DBInstance resource, once the AvailabilityZone field is set by the user, it cannot be modified.
807
807
808
808
By telling the code generator that this field is immutable, it will generate code in the `sdk.go` file that [checks for whether a user has modified any immutable fields](https://github.com/aws-controllers-k8s/rds-controller/blob/f8b5d69f822bfc809cbfa25ef7ad60b58a4af22e/pkg/resource/db_instance/sdk.go#L2768) and set a Condition on the resource if so:
### Controlling where a field's definition comes from
834
+
### `from`: Controlling the source of a field's definition
835
835
836
836
During API inference, `ack-generate` inspects the AWS service API model definition and discovers resource fields by looking at the Input and Output shapes of the `Create` API call for that resource. Members of the Input shape will go in the `Spec` and members of the Output shape *that are not also in the Input shape* will go into the `Status`.
837
837
@@ -895,7 +895,7 @@ resources:
895
895
896
896
**NOTE on maintainability:** Another way of solving this particular problem would be to use a completely new custom field. However, *we only use this as a last resort*. The reason why we prefer to use the `from:` configuration option is because this approach will adapt over time with changes to the AWS service API model, including documentation *about* those fields, whereas completely new custom fields will always need to be hand-rolled and no API documentation will be auto-generated for them.
897
897
898
-
### Annotating a fieldas a "Printer Column"
898
+
### `print`: Controlling a field's output as printer columns in `kubectl get`
899
899
900
900
If we want to add one of a Resource's fields to the output of the `kubectl get` command, we can do so by annotating that field's configuration with a `print:` section. An example of this is in the EC2 controller's [`ElasticIPAddress` Resource](https://github.com/aws-controllers-k8s/ec2-controller/blob/b161bb67b0e5d8b24588676ae29d0f1e587bd42a/generator.yaml#L244), for which we would like to include the `PublicIP` field in the output of `kubectl get`:
901
901
@@ -914,7 +914,7 @@ Including this in the field's configuration will cause the code generator to pro
914
914
915
915
**NOTE** this configuration is used to include printer columns in the output at the level of individual fields. One can also create [additional printer columns](#including-additional-printer-columns) at the level of Resources.
916
916
917
-
### Controlling field "late initialization"
917
+
### `late_initialize`: Late initialization of a field
918
918
919
919
[Late initialization of a field](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#controller-assigned-defaults-aka-late-initialization) is a Kubernetes Resource Model concept that allows for a nil-valued field to be defaulted to some value *after the resource has been successfully created*. This is akin to a database table field's "default value".
920
920
@@ -934,7 +934,7 @@ resources:
934
934
935
935
**NOTE**: the `late_initialize:` configuration option is currently a struct with a couple member fields that are not yet implemented (as of Dec 2022), which is why you need to use the `{}` notation.
936
936
937
-
### Informing the code generator that a field refers to another Resource
937
+
### `references`: Making a field refer to another Resource
938
938
939
939
One custom resource can refer to another custom resource using something called Resource References. The Go code that handles the validation and resolution of Resource References is generated by `ack-generate`.
940
940
@@ -1036,7 +1036,7 @@ Along with the above 4 main ResourceManager methods, there are a number of gener
1036
1036
* create the SDK input shape used when making HTTP requests to AWS APIs
1037
1037
* process responses from those AWS APIs
1038
1038
1039
-
#### `sdk_*_pre_build_request`
1039
+
#### `sdk_*_pre_build_request`: before validation and construction of Input shape
1040
1040
1041
1041
The `sdk_*_pre_build_request` hooks are called _before_ the call to construct the Input shape that is used in the API operation and therefore _before_ any call to validate that Input shape.
1042
1042
@@ -1143,7 +1143,7 @@ What you can see above is the use of the `pre_build_request` hook point to updat
1143
1143
> **TOP TIP (1)**:
1144
1144
> Note the use of `delta.DifferentAt()` in the code above. This is the recommended best practice for determining whether a particular field at a supplied field path has diverged between the desired and latest observed resource state.
1145
1145
1146
-
#### `sdk_*_post_build_request`
1146
+
#### `sdk_*_post_build_request`: after construction of Input shape
1147
1147
1148
1148
The `post_build_request` hooks are called AFTER the call to construct the Input shape but _before_ the API operation.
1149
1149
@@ -1207,33 +1207,33 @@ As you can see, we add some custom validation and normalization of the Input sha
1207
1207
> **TOP TIP (2)**:
1208
1208
> Note the verbose usage of nil-checks. **_This is very important_**. `aws-sdk-go` does not have automatic protection against `nil` pointer dereferencing. *All* fields in an `aws-sdk-go` shape are **pointer types**. This means you should **always** do your own nil-checks when dereferencing **any** field in **any** shape.
1209
1209
1210
-
#### `sdk_*_post_request`
1210
+
#### `sdk_*_post_request`: after the API operation
1211
1211
1212
1212
The `post_request` hooks are called IMMEDIATELY AFTER the API operation `aws-sdk-go` client call. These hooks will have access to a Go variable named `resp` that refers to the `aws-sdk-go` client response and a Go variable named `respErr` that refers to any error returned from the `aws-sdk-go` client call.
1213
1213
1214
-
#### `sdk_*_pre_set_output`
1214
+
#### `sdk_*_pre_set_output`: before validation of Output shape
1215
1215
1216
-
The `pre_set_output` hooks are called BEFORE the code that processes the Outputshape (the `pkg/generate/code.SetOutput` function). These hooks will have access to a Go variable named `ko` that represents the concrete Kubernetes CR object that will be returned from the main method (`sdkFind`, `sdkCreate`, etc). This `ko` variable will have been defined immediately before the `pre_set_output` hooks as a copy of the resource that is supplied to the main method, like so:
1216
+
The `pre_set_output` hooks are called BEFORE the code that processes the Output shape (the `pkg/generate/code.SetOutput` function). These hooks will have access to a Go variable named `ko` that represents the concrete Kubernetes CR object that will be returned from the main method (`sdkFind`, `sdkCreate`, etc). This `ko` variable will have been defined immediately before the `pre_set_output` hooks as a copy of the resource that is supplied to the main method, like so:
1217
1217
1218
1218
```go
1219
1219
// Merge in the information we read from the API call above to the copy of
1220
1220
// the original Kubernetes object we passed to the function
1221
1221
ko:= r.ko.DeepCopy()
1222
1222
```
1223
1223
1224
-
#### `sdk_*_post_set_output`
1224
+
#### `sdk_*_post_set_output`: after merging data from API response & k8s object
1225
1225
1226
1226
The `post_set_output` hooks are called AFTER the the information from the API call is merged with the copy of the original Kubernetes object. These hooks will have access to the updated Kubernetes object `ko`, the response of the API call (and the original Kubernetes CR object if it's `sdkUpdate`).
1227
1227
1228
-
#### `sdk_file_end`
1228
+
#### `sdk_file_end`: miscellaneous catch-all
1229
1229
1230
1230
The `sdk_file_end` is a generic hook point that occurs outside the scope of any specific `AWSResourceManager` method and can be used to place commonly-generated code inside the `sdk.go` file.
1231
1231
1232
1232
**_NOTE(jaypipes): This is the weirdest of the hooks... need to cleanly explain this!_**
1233
1233
1234
1234
### The comparison hook points
1235
1235
1236
-
#### `delta_pre_compare`
1236
+
#### `delta_pre_compare`: before comparing resources
1237
1237
1238
1238
The `delta_pre_compare` hooks are called _before_ the generated code that compares two resources.
1239
1239
@@ -1278,7 +1278,7 @@ func compareTags(
1278
1278
1279
1279
[`commonutil.EqualTags`](https://github.com/aws-controllers-k8s/iam-controller/blob/b6a62ca48c1aea7ab78e62fb3ad6845335c1f1c2/pkg/util/tags.go#L22-L59) properly handles the comparison of lists of Tag structs.
1280
1280
1281
-
#### `delta_post_compare`
1281
+
#### `delta_post_compare`: after comparing resources
1282
1282
1283
1283
The `delta_post_compare` hooks are called _after_ the generated code that compares two resources.
1284
1284
@@ -1288,52 +1288,52 @@ However, the `delta_post_compare` hook point can be useful if you want to add so
1288
1288
1289
1289
### The late initialization hook points
1290
1290
1291
-
#### `late_initialize_pre_read_one`
1291
+
#### `late_initialize_pre_read_one`: before the `readOne`
1292
1292
1293
1293
The `late_initialize_pre_read_one` hooks are called _before_ making the `readOne` call inside the `AWSResourceManager.LateInitialize()` method.
1294
1294
TODO
1295
-
#### `late_initialize_post_read_one`
1295
+
#### `late_initialize_post_read_one`: after the `readOne`
1296
1296
1297
1297
The `late_initialize_post_read_one` hooks are called _after_ making the `readOne` call inside the `AWSResourceManager.LateInitialize()` method.
1298
1298
TODO
1299
1299
### The reference hook points
1300
1300
1301
-
#### `references_pre_resolve`
1301
+
#### `references_pre_resolve`: before resolving references
1302
1302
1303
1303
The `references_pre_resolve` hook is called _before_ resolving the references for all Reference fields inside the `AWSResourceManager.ResolveReferences()` method.
1304
1304
TODO
1305
-
#### `references_post_resolve`
1305
+
#### `references_post_resolve`: after resolving references
1306
1306
1307
1307
The `references_post_resolve` hook is called _after_ resolving the references for all Reference fields inside the `AWSResourceManager.ResolveReferences()` method.
1308
1308
TODO
1309
1309
### The tags hook points
1310
1310
1311
-
#### `ensure_tags`
1311
+
#### `ensure_tags`: custom `EnsureTags` method
1312
1312
1313
1313
The `ensure_tags` hook provides a complete custom implementation for the `AWSResourceManager.EnsureTags()` method.
1314
1314
TODO
1315
1315
1316
-
#### `convert_tags`
1316
+
#### `convert_tags`: custom `ToACKTags` and `FromACKTags` methods
1317
1317
1318
1318
The `convert_tags` hook provides a complete custom implementation for the `ToACKTags` and `FromACKTags` methods.
1319
1319
TODO
1320
1320
1321
-
#### `convert_tags_pre_to_ack_tags`
1321
+
#### `convert_tags_pre_to_ack_tags`: before converting k8s tags to ACK tags
1322
1322
1323
1323
The `convert_tags_pre_to_ack_tags` hooks are called _before_ converting the K8s resource tags into ACK tags.
1324
1324
TODO
1325
1325
1326
-
#### `convert_tags_post_to_ack_tags`
1326
+
#### `convert_tags_post_to_ack_tags`: after converting k8s tags to ACK tags
1327
1327
1328
1328
The `convert_tags_post_to_ack_tags` hooks are called _after_ converting the K8s resource tags into ACK tags.
1329
1329
TODO
1330
1330
1331
-
#### `convert_tags_pre_from_ack_tags`
1331
+
#### `convert_tags_pre_from_ack_tags`: before converting ACK tags to k8s tags
1332
1332
1333
1333
The `convert_tags_pre_from_ack_tags` hooks are called _before_ converting the ACK tags into K8s resource tags.
1334
1334
TODO
1335
1335
1336
-
#### `convert_tags_post_from_ack_tags`
1336
+
#### `convert_tags_post_from_ack_tags`: after converting ACK tags to k8s tags
1337
1337
1338
1338
The `convert_tags_post_from_ack_tags` hooks are called _after_ converting the ACK tags into K8s resource tags.
0 commit comments