Skip to content

Commit

Permalink
codegen: Update API client generation to not support new JSONValue me…
Browse files Browse the repository at this point in the history
…mbers (#4269)

Updates the SDK's code generation to stop supporting new API modeled
JSONValue parameters. The SDK's JSONValue type is only compatible with
JSON documents with a top level JSON Object. JSON Lists, Strings,
Scalars, are not compatible. This prevents JSON Value working with some
APIs such as Amazon Lex Runtime Service's operations.

This update also introduces the breaking change to
service/lexruntimeservice package by changing the following parameters
from a JSONValue to string type.
* PostContentInput.ActiveContexts
* PutContentOutput.AlternativeIntents
* PutContentOutput.ActiveContexts
* PutSessionOutput.ActiveContexts
  • Loading branch information
jasdel authored Feb 15, 2022
1 parent 796368e commit 93134df
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 25 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
### SDK Features
* `codegen`: Updates the SDK's code generation to stop supporting new API modeled JSONValue parameters. The SDK's JSONValue type is only compatible with JSON documents with a top level JSON Object. JSON Lists, Strings, Scalars, are not compatible. This prevents JSON Value working with some APIs such as Amazon Lex Runtime Service's operations.
* Related to [#4264](https://github.com/aws/aws-sdk-go/pull/4264) and [#4258](https://github.com/aws/aws-sdk-go/issues/4258)

### SDK Enhancements

### SDK Bugs
* `service/lexruntimeservice`: Introduces a breaking change for following parameters from a JSONValue to string type, because the SDKs JSONValue is not compatible with JSON documents of lists.
* PostContentInput.ActiveContexts
* PutContentOutput.AlternativeIntents
* PutContentOutput.ActiveContexts
* PutSessionOutput.ActiveContexts
* Fixes [#4258](https://github.com/aws/aws-sdk-go/issues/4258)
3 changes: 3 additions & 0 deletions private/model/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type API struct {
// Set to true to not generate struct field accessors
NoGenStructFieldAccessors bool

// Set to not remove unsupported (non-legacy) JSON from API, (for generated tests).
NoRemoveUnsupportedJSONValue bool

BaseImportPath string

initialized bool
Expand Down
71 changes: 71 additions & 0 deletions private/model/api/customization_passes.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package api
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -397,3 +398,73 @@ func backfillAuthType(typ AuthType, opNames ...string) func(*API) error {
return nil
}
}

// Must be invoked with the original shape name
func removeUnsupportedJSONValue(a *API) error {
for shapeName, shape := range a.Shapes {
switch shape.Type {
case "structure":
for refName, ref := range shape.MemberRefs {
if !ref.JSONValue {
continue
}
if err := removeUnsupportedShapeRefJSONValue(a, shapeName, refName, ref); err != nil {
return fmt.Errorf("failed remove unsupported JSONValue from %v.%v, %v",
shapeName, refName, err)
}
}
case "list":
if !shape.MemberRef.JSONValue {
continue
}
if err := removeUnsupportedShapeRefJSONValue(a, shapeName, "", &shape.MemberRef); err != nil {
return fmt.Errorf("failed remove unsupported JSONValue from %v, %v",
shapeName, err)
}
case "map":
if !shape.ValueRef.JSONValue {
continue
}
if err := removeUnsupportedShapeRefJSONValue(a, shapeName, "", &shape.ValueRef); err != nil {
return fmt.Errorf("failed remove unsupported JSONValue from %v, %v",
shapeName, err)
}
}
}

return nil
}

func removeUnsupportedShapeRefJSONValue(a *API, parentName, refName string, ref *ShapeRef) (err error) {
var found bool

defer func() {
if !found && err == nil {
log.Println("removing JSONValue", a.PackageName(), parentName, refName)
ref.JSONValue = false
ref.SuppressedJSONValue = true
}
}()

legacyShapes, ok := legacyJSONValueShapes[a.PackageName()]
if !ok {
return nil
}

legacyShape, ok := legacyShapes[parentName]
if !ok {
return nil
}

switch legacyShape.Type {
case "structure":
_, ok = legacyShape.StructMembers[refName]
found = ok
case "list":
found = legacyShape.ListMemberRef
case "map":
found = legacyShape.MapValueRef
}

return nil
}
257 changes: 257 additions & 0 deletions private/model/api/legacy_jsonvalue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
//go:build codegen
// +build codegen

package api

type legacyJSONValues struct {
Type string
StructMembers map[string]struct{}
ListMemberRef bool
MapValueRef bool
}

var legacyJSONValueShapes = map[string]map[string]legacyJSONValues{
"braket": map[string]legacyJSONValues{
"CreateQuantumTaskRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"action": struct{}{},
"deviceParameters": struct{}{},
},
},
"GetDeviceResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"deviceCapabilities": struct{}{},
},
},
"GetQuantumTaskResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"deviceParameters": struct{}{},
},
},
},
"cloudwatchevidently": map[string]legacyJSONValues{
"EvaluateFeatureRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"evaluationContext": struct{}{},
},
},
"EvaluateFeatureResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"details": struct{}{},
},
},
"EvaluationRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"evaluationContext": struct{}{},
},
},
"EvaluationResult": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"details": struct{}{},
},
},
"Event": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"data": struct{}{},
},
},
"ExperimentReport": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"content": struct{}{},
},
},
"MetricDefinition": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"eventPattern": struct{}{},
},
},
"MetricDefinitionConfig": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"eventPattern": struct{}{},
},
},
},
"cloudwatchrum": map[string]legacyJSONValues{
"RumEvent": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"details": struct{}{},
"metadata": struct{}{},
},
},
},
"lexruntimeservice": map[string]legacyJSONValues{
"PostContentRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"requestAttributes": struct{}{},
//"ActiveContexts": struct{}{}, - Disabled because JSON List
"sessionAttributes": struct{}{},
},
},
"PostContentResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
// "alternativeIntents": struct{}{}, - Disabled because JSON List
"sessionAttributes": struct{}{},
"nluIntentConfidence": struct{}{},
"slots": struct{}{},
//"activeContexts": struct{}{}, - Disabled because JSON List
},
},
"PutSessionResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
// "activeContexts": struct{}{}, - Disabled because JSON List
"slots": struct{}{},
"sessionAttributes": struct{}{},
},
},
},
"lookoutequipment": map[string]legacyJSONValues{
"DatasetSchema": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"InlineDataSchema": struct{}{},
},
},
"DescribeDatasetResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Schema": struct{}{},
},
},
"DescribeModelResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Schema": struct{}{},
"ModelMetrics": struct{}{},
},
},
},
"networkmanager": map[string]legacyJSONValues{
"CoreNetworkPolicy": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"PolicyDocument": struct{}{},
},
},
"GetResourcePolicyResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"PolicyDocument": struct{}{},
},
},
"PutCoreNetworkPolicyRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"PolicyDocument": struct{}{},
},
},
"PutResourcePolicyRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"PolicyDocument": struct{}{},
},
},
},
"personalizeevents": map[string]legacyJSONValues{
"Event": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"properties": struct{}{},
},
},
"Item": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"properties": struct{}{},
},
},
"User": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"properties": struct{}{},
},
},
},
"pricing": map[string]legacyJSONValues{
"PriceList": legacyJSONValues{
Type: "list",
ListMemberRef: true,
},
},
"rekognition": map[string]legacyJSONValues{
"HumanLoopActivationOutput": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"HumanLoopActivationConditionsEvaluationResults": struct{}{},
},
},
},
"sagemaker": map[string]legacyJSONValues{
"HumanLoopActivationConditionsConfig": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"HumanLoopActivationConditions": struct{}{},
},
},
},
"schemas": map[string]legacyJSONValues{
"GetResourcePolicyResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Policy": struct{}{},
},
},
"PutResourcePolicyRequest": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Policy": struct{}{},
},
},
"PutResourcePolicyResponse": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Policy": struct{}{},
},
},
"GetResourcePolicyOutput": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Policy": struct{}{},
},
},
"PutResourcePolicyInput": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Policy": struct{}{},
},
},
"PutResourcePolicyOutput": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"Policy": struct{}{},
},
},
},
"textract": map[string]legacyJSONValues{
"HumanLoopActivationOutput": legacyJSONValues{
Type: "structure",
StructMembers: map[string]struct{}{
"HumanLoopActivationConditionsEvaluationResults": struct{}{},
},
},
},
}
5 changes: 5 additions & 0 deletions private/model/api/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ func (a *API) Setup() error {
if err := a.validateNoDocumentShapes(); err != nil {
return err
}
if !a.NoRemoveUnsupportedJSONValue {
if err := removeUnsupportedJSONValue(a); err != nil {
return fmt.Errorf("failed to remove unsupported JSONValue from API, %v", err)
}
}
a.setServiceAliaseName()
a.setMetadataEndpointsKey()
a.writeShapeNames()
Expand Down
Loading

0 comments on commit 93134df

Please sign in to comment.