Skip to content

Commit bd787f6

Browse files
integrated-response-transform
Summary: - Refine and improve response transform interface. - Consume new core testing logic.
1 parent bcfe5c9 commit bd787f6

7 files changed

Lines changed: 129 additions & 71 deletions

File tree

.github/workflows/build.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,21 +164,21 @@ jobs:
164164
openssl req -x509 -keyout test/server/mtls/credentials/pg_server_key.pem -out test/server/mtls/credentials/pg_server_cert.pem -config test/server/mtls/openssl.cnf -days 365
165165
openssl req -x509 -keyout test/server/mtls/credentials/pg_client_key.pem -out test/server/mtls/credentials/pg_client_cert.pem -config test/server/mtls/openssl.cnf -days 365
166166
openssl req -x509 -keyout test/server/mtls/credentials/pg_rubbish_key.pem -out test/server/mtls/credentials/pg_rubbish_cert.pem -config test/server/mtls/openssl.cnf -days 365
167-
python3 test/python/registry-rewrite.py
167+
python3 test/python/stackql_test_tooling/registry_rewrite.py
168168
169169
- name: Create mock routed services for local tests
170170
run: |
171-
python3 stackql-core/test/python/registry-rewrite.py \
171+
python3 stackql-core/test/python/stackql_test_tooling/registry_rewrite.py \
172172
--srcdir $(pwd)/test/registry-simple/src \
173173
--destdir $(pwd)/test/registry-mocked/src
174174
175175
- name: Start Core Test Mocks
176176
working-directory: stackql-core
177177
run: |
178178
pgrep -f flask | xargs kill -9 || true
179-
flask --app=./test/python/flask/gcp/app run --cert=./test/server/mtls/credentials/pg_server_cert.pem --key=./test/server/mtls/credentials/pg_server_key.pem --host 0.0.0.0 --port 1080 &
180-
flask --app=./test/python/flask/oauth2/token_srv run --cert=./test/server/mtls/credentials/pg_server_cert.pem --key=./test/server/mtls/credentials/pg_server_key.pem --host 0.0.0.0 --port 2091 &
181-
flask --app=./test/python/flask/aws/app run --cert=./test/server/mtls/credentials/pg_server_cert.pem --key=./test/server/mtls/credentials/pg_server_key.pem --host 0.0.0.0 --port 1091 &
179+
flask --app=./test/python/stackql_test_tooling/flask/gcp/app run --cert=./test/server/mtls/credentials/pg_server_cert.pem --key=./test/server/mtls/credentials/pg_server_key.pem --host 0.0.0.0 --port 1080 &
180+
flask --app=./test/python/stackql_test_tooling/flask/oauth2/token_srv run --cert=./test/server/mtls/credentials/pg_server_cert.pem --key=./test/server/mtls/credentials/pg_server_key.pem --host 0.0.0.0 --port 2091 &
181+
flask --app=./test/python/stackql_test_tooling/flask/aws/app run --cert=./test/server/mtls/credentials/pg_server_cert.pem --key=./test/server/mtls/credentials/pg_server_key.pem --host 0.0.0.0 --port 1091 &
182182
183183
- name: Run core mocked testing
184184
working-directory: stackql-core

anysdk/expectedResponse.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ type ExpectedResponse interface {
1111
GetOpenAPIDocKey() string
1212
GetObjectKey() string
1313
GetSchema() Schema
14-
getOverrideSchema() (*openapi3.Schema, bool)
14+
getOverrideSchema() (*openapi3.SchemaRef, bool)
15+
setOverrideSchemaValue(*openapi3.Schema)
1516
GetTransform() (Transform, bool)
1617
//
1718
setSchema(Schema)
@@ -24,8 +25,8 @@ type standardExpectedResponse struct {
2425
OpenAPIDocKey string `json:"openAPIDocKey,omitempty" yaml:"openAPIDocKey,omitempty"`
2526
ObjectKey string `json:"objectKey,omitempty" yaml:"objectKey,omitempty"`
2627
Schema Schema
27-
OverrideSchema *openapi3.Schema `json:"schema_override,omitempty" yaml:"schema_override,omitempty"`
28-
Transform *standardTransform `json:"transform,omitempty" yaml:"transform,omitempty"`
28+
OverrideSchema *openapi3.SchemaRef `json:"schema_override,omitempty" yaml:"schema_override,omitempty"`
29+
Transform *standardTransform `json:"transform,omitempty" yaml:"transform,omitempty"`
2930
}
3031

3132
func (er *standardExpectedResponse) setBodyMediaType(s string) {
@@ -40,6 +41,13 @@ func (er *standardExpectedResponse) GetBodyMediaType() string {
4041
return er.BodyMediaType
4142
}
4243

44+
func (er *standardExpectedResponse) setOverrideSchemaValue(s *openapi3.Schema) {
45+
if er.OverrideSchema == nil {
46+
er.OverrideSchema = &openapi3.SchemaRef{}
47+
}
48+
er.OverrideSchema.Value = s
49+
}
50+
4351
func (er *standardExpectedResponse) GetOpenAPIDocKey() string {
4452
return er.OpenAPIDocKey
4553
}
@@ -49,13 +57,13 @@ func (er *standardExpectedResponse) GetObjectKey() string {
4957
}
5058

5159
func (er *standardExpectedResponse) GetSchema() Schema {
52-
if er.OverrideSchema != nil {
53-
return newSchema(er.OverrideSchema, nil, "", "")
60+
if er.OverrideSchema != nil && er.OverrideSchema.Value != nil {
61+
return newSchema(er.OverrideSchema.Value, nil, "", "")
5462
}
5563
return er.Schema
5664
}
5765

58-
func (er *standardExpectedResponse) getOverrideSchema() (*openapi3.Schema, bool) {
66+
func (er *standardExpectedResponse) getOverrideSchema() (*openapi3.SchemaRef, bool) {
5967
isNilSchema := er.OverrideSchema == nil
6068
if isNilSchema {
6169
return nil, false

anysdk/loader.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type DiscoveryDoc interface {
3939
}
4040

4141
type anySdkLoader interface {
42+
loadOpenapiDocFromBytes(bytes []byte) (*openapi3.T, error)
4243
loadFromBytes(bytes []byte) (OpenAPIService, error)
4344
loadFromBytesWithProvider(bytes []byte, prov Provider) (OpenAPIService, error)
4445
loadFromBytesAndResources(rr ResourceRegister, resourceKey string, bytes []byte) (OpenAPIService, error)
@@ -94,7 +95,13 @@ func LoadProviderAndServiceFromPaths(
9495
}
9596
return svc, nil
9697
case client.LocalTemplated:
98+
l := newLoader()
99+
doc, err := l.loadOpenapiDocFromBytes(b)
100+
if err != nil {
101+
return nil, err
102+
}
97103
rv := new(localTemplatedService)
104+
rv.OpenapiSvc = doc
98105
err = yamlconv.Unmarshal(b, rv)
99106
if err != nil {
100107
return nil, err
@@ -130,6 +137,17 @@ func loadResourcesShallow(ps ProviderService, bt []byte) (ResourceRegister, erro
130137
return rv, nil
131138
}
132139

140+
func (l *standardLoader) loadOpenapiDocFromBytes(bytes []byte) (*openapi3.T, error) {
141+
doc, err := l.LoadFromData(bytes)
142+
if err != nil {
143+
return nil, err
144+
}
145+
if doc == nil {
146+
return nil, fmt.Errorf("OpenAPIService.loadOpenapiDocFromBytes() failure")
147+
}
148+
return doc, nil
149+
}
150+
133151
func (l *standardLoader) loadFromBytes(bytes []byte) (OpenAPIService, error) {
134152
doc, err := l.LoadFromData(bytes)
135153
if err != nil {
@@ -933,8 +951,14 @@ func (loader *standardLoader) resolveExpectedResponse(doc OpenAPIService, op *op
933951
bmt := component.GetBodyMediaType()
934952
ek := component.GetOpenAPIDocKey()
935953
overrideSchema, isOverrideSchema := component.getOverrideSchema()
936-
if isOverrideSchema {
937-
s := newSchema(overrideSchema, doc, "", "")
954+
if isOverrideSchema && overrideSchema.Ref != "" {
955+
schemaKey := strings.TrimPrefix(overrideSchema.Ref, "#/components/schemas/")
956+
sr := doc.getT().Components.Schemas[schemaKey]
957+
if sr == nil || sr.Value == nil {
958+
return fmt.Errorf("schema '%s' not found in components", schemaKey)
959+
}
960+
component.setOverrideSchemaValue(sr.Value)
961+
s := newSchema(sr.Value, doc, "", "")
938962
component.setSchema(s)
939963
} else if bmt != "" && ek != "" {
940964
ekObj, ok := op.Responses[ek]

anysdk/operation_store.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,8 +1366,8 @@ func (op *standardOpenAPIOperationStore) GetResponseBodySchemaAndMediaType() (Sc
13661366
}
13671367

13681368
func (op *standardOpenAPIOperationStore) getResponseBodySchemaAndMediaType() (Schema, string, error) {
1369-
if op.Response != nil && op.Response.OverrideSchema != nil {
1370-
return newSchema(op.Response.OverrideSchema, op.GetService(), "", ""), "", nil
1369+
if op.Response != nil && op.Response.OverrideSchema != nil && op.Response.OverrideSchema.Value != nil {
1370+
return newSchema(op.Response.OverrideSchema.Value, op.GetService(), "", ""), "", nil
13711371
}
13721372
if op.Response != nil && op.Response.Schema != nil {
13731373
mediaType := op.Response.BodyMediaType
@@ -1381,8 +1381,8 @@ func (op *standardOpenAPIOperationStore) getResponseBodySchemaAndMediaType() (Sc
13811381

13821382
func (op *standardOpenAPIOperationStore) GetSelectSchemaAndObjectPath() (Schema, string, error) {
13831383
k := op.lookupSelectItemsKey()
1384-
if op.Response != nil && op.Response.OverrideSchema != nil {
1385-
return newSchema(op.Response.OverrideSchema, op.GetService(), "", ""), k, nil
1384+
if op.Response != nil && op.Response.OverrideSchema != nil && op.Response.OverrideSchema.Value != nil {
1385+
return newSchema(op.Response.OverrideSchema.Value, op.GetService(), "", ""), k, nil
13861386
}
13871387
if op.Response != nil && op.Response.Schema != nil {
13881388
return op.Response.Schema.getSelectItemsSchema(k, op.getOptimalResponseMediaType())

anysdk/service.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type Service interface {
2323
GetName() string
2424
GetResource(resourceName string) (Resource, error)
2525
GetSchema(key string) (Schema, error)
26+
getT() *openapi3.T
2627
}
2728

2829
type OpenAPIService interface {
@@ -47,13 +48,18 @@ type OpenAPIService interface {
4748
}
4849

4950
type localTemplatedService struct {
51+
OpenapiSvc *openapi3.T `json:"-" yaml:"-"`
5052
Name string `json:"name" yaml:"name"`
5153
Rsc map[string]*standardResource `json:"resources" yaml:"resources"`
5254
StackQLConfig StackQLConfig `json:"-" yaml:"-"`
5355
ProviderService ProviderService `json:"-" yaml:"-"` // upwards traversal
5456
Provider Provider `json:"-" yaml:"-"` // upwards traversal
5557
}
5658

59+
func (sv *localTemplatedService) getT() *openapi3.T {
60+
return sv.OpenapiSvc
61+
}
62+
5763
func (sv *localTemplatedService) GetServers() (openapi3.Servers, bool) {
5864
return nil, false
5965
}

test/registry-simple/src/aws/v0.1.0/services/ec2.yaml

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -251,33 +251,7 @@ components:
251251
openAPIDocKey: '200'
252252
objectKey: '/DescribeVolumesResponse/volumeSet/item'
253253
schema_override:
254-
title: Key Display
255-
type: object
256-
properties:
257-
nextPageToken:
258-
type: string
259-
description: The <code>NextToken</code> value to include in a future <code>DescribeVolumes</code> request. When the results of a <code>DescribeVolumes</code> request exceed <code>MaxResults</code>, this value can be used to retrieve the next page of results. This value is <code>null</code> when there are no more results to return.
260-
line_items:
261-
type: list
262-
items:
263-
type: object
264-
properties:
265-
type:
266-
type: string
267-
description: The key type
268-
example: x509
269-
not_before:
270-
type: string
271-
description: Textual date representation of the key's not before date.
272-
example: Mar 22 02:50:46 2025 GMT
273-
not_after:
274-
type: string
275-
description: Textual date representation of the key's not after date.
276-
example: Mar 22 02:50:46 2025 GMT
277-
public_key_algorithm:
278-
type: string
279-
description: The public key algorithm used by the key.
280-
example: rsaEncryption
254+
$ref: '#/components/schemas/DisplayVolumesSchema'
281255
transform:
282256
body: >
283257
{
@@ -404,6 +378,42 @@ components:
404378
- xml:
405379
name: nextToken
406380
description: The <code>NextToken</code> value returned from a previous paginated <code>DescribeVolumes</code> request where <code>MaxResults</code> was used and the results exceeded the value of that parameter. Pagination continues from the end of the previous results that returned the <code>NextToken</code> value. This value is <code>null</code> when there are no more results to return.
381+
DisplayVolumesSchema:
382+
title: Key Display
383+
type: object
384+
properties:
385+
next_page_token:
386+
type: string
387+
description: The <code>NextToken</code> value to include in a future <code>DescribeVolumes</code> request. When the results of a <code>DescribeVolumes</code> request exceed <code>MaxResults</code>, this value can be used to retrieve the next page of results. This value is <code>null</code> when there are no more results to return.
388+
line_items:
389+
type: array
390+
items:
391+
type: object
392+
properties:
393+
volume_type:
394+
type: string
395+
description: The volume type
396+
example: gp3
397+
volume_id:
398+
type: string
399+
example: vol-00aaaccc111000000
400+
snapshot_id:
401+
type: string
402+
status:
403+
type: string
404+
availability_zone:
405+
type: string
406+
create_time:
407+
type: string
408+
description: Textual datetime representation of the volume's creation time.
409+
example: '2024-08-20T05:47:06.409Z'
410+
size:
411+
type: integer
412+
example: 8
413+
encrypted:
414+
type: bool
415+
multi_attach_enabled:
416+
type: bool
407417
DescribeVolumesResult:
408418
type: object
409419
example:

test/registry/src/aws/v0.1.0/services/ec2.yaml

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -246,33 +246,7 @@ components:
246246
openAPIDocKey: '200'
247247
objectKey: '/DescribeVolumesResponse/volumeSet/item'
248248
schema_override:
249-
title: Key Display
250-
type: object
251-
properties:
252-
nextPageToken:
253-
type: string
254-
description: The <code>NextToken</code> value to include in a future <code>DescribeVolumes</code> request. When the results of a <code>DescribeVolumes</code> request exceed <code>MaxResults</code>, this value can be used to retrieve the next page of results. This value is <code>null</code> when there are no more results to return.
255-
line_items:
256-
type: list
257-
items:
258-
type: object
259-
properties:
260-
type:
261-
type: string
262-
description: The key type
263-
example: x509
264-
not_before:
265-
type: string
266-
description: Textual date representation of the key's not before date.
267-
example: Mar 22 02:50:46 2025 GMT
268-
not_after:
269-
type: string
270-
description: Textual date representation of the key's not after date.
271-
example: Mar 22 02:50:46 2025 GMT
272-
public_key_algorithm:
273-
type: string
274-
description: The public key algorithm used by the key.
275-
example: rsaEncryption
249+
$ref: '#/components/schemas/DisplayVolumesSchema'
276250
transform:
277251
body: >
278252
{
@@ -399,6 +373,42 @@ components:
399373
- xml:
400374
name: nextToken
401375
description: The <code>NextToken</code> value returned from a previous paginated <code>DescribeVolumes</code> request where <code>MaxResults</code> was used and the results exceeded the value of that parameter. Pagination continues from the end of the previous results that returned the <code>NextToken</code> value. This value is <code>null</code> when there are no more results to return.
376+
DisplayVolumesSchema:
377+
title: Key Display
378+
type: object
379+
properties:
380+
next_page_token:
381+
type: string
382+
description: The <code>NextToken</code> value to include in a future <code>DescribeVolumes</code> request. When the results of a <code>DescribeVolumes</code> request exceed <code>MaxResults</code>, this value can be used to retrieve the next page of results. This value is <code>null</code> when there are no more results to return.
383+
line_items:
384+
type: array
385+
items:
386+
type: object
387+
properties:
388+
volume_type:
389+
type: string
390+
description: The volume type
391+
example: gp3
392+
volume_id:
393+
type: string
394+
example: vol-00aaaccc111000000
395+
snapshot_id:
396+
type: string
397+
status:
398+
type: string
399+
availability_zone:
400+
type: string
401+
create_time:
402+
type: string
403+
description: Textual datetime representation of the volume's creation time.
404+
example: '2024-08-20T05:47:06.409Z'
405+
size:
406+
type: integer
407+
example: 8
408+
encrypted:
409+
type: bool
410+
multi_attach_enabled:
411+
type: bool
402412
DescribeVolumesResult:
403413
type: object
404414
example:

0 commit comments

Comments
 (0)