From ff378862551fcf96fbbcbb23b3cdbc391a958186 Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Wed, 29 Jan 2025 13:23:25 +0530 Subject: [PATCH 1/4] fix: changed dql routes format to show dict for service --- pkg/file/builder.go | 27 +++++++++++++++++++++++---- pkg/file/types.go | 7 +++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/pkg/file/builder.go b/pkg/file/builder.go index a665aff..43a20a3 100644 --- a/pkg/file/builder.go +++ b/pkg/file/builder.go @@ -1748,7 +1748,7 @@ func (b *stateBuilder) ingestCustomEntities(customEntities []FCustomEntity) { } func (b *stateBuilder) ingestDeGraphqlRoute(degraphqlRouteEntity FCustomEntity) { - degraphqlRoute, err := copyToDegraphqlRoute(degraphqlRouteEntity) + degraphqlRoute, err := b.copyToDegraphqlRoute(degraphqlRouteEntity) if err != nil { b.err = err return @@ -1771,7 +1771,7 @@ func (b *stateBuilder) ingestDeGraphqlRoute(degraphqlRouteEntity FCustomEntity) b.rawState.DegraphqlRoutes = append(b.rawState.DegraphqlRoutes, °raphqlRoute.DegraphqlRoute) } -func copyToDegraphqlRoute(fcEntity FCustomEntity) (DegraphqlRoute, error) { +func (b *stateBuilder) copyToDegraphqlRoute(fcEntity FCustomEntity) (DegraphqlRoute, error) { degraphqlRoute := DegraphqlRoute{} if fcEntity.ID != nil { degraphqlRoute.ID = fcEntity.ID @@ -1782,9 +1782,28 @@ func copyToDegraphqlRoute(fcEntity FCustomEntity) (DegraphqlRoute, error) { } if fcEntity.Fields["service"] != nil { - if service, ok := fcEntity.Fields["service"].(*string); ok { + if service, ok := fcEntity.Fields["service"].(map[string]interface{}); ok { + var serviceID string + var serviceName string + s, ok := service["id"].(string) + if ok { + serviceID = s + } + s, ok = service["name"].(string) + if ok { + serviceName = s + } + + if serviceID == "" && serviceName != "" { + s, err := b.intermediate.Services.Get(serviceName) + if err != nil { + return DegraphqlRoute{}, fmt.Errorf("service %v not found", serviceName) + } + serviceID = *s.ID + } + degraphqlRoute.Service = &kong.Service{ - ID: service, + ID: kong.String(serviceID), } } } diff --git a/pkg/file/types.go b/pkg/file/types.go index d7dd6d4..a387b60 100644 --- a/pkg/file/types.go +++ b/pkg/file/types.go @@ -991,7 +991,10 @@ func copyFromDegraphqlRoute(dRoute DegraphqlRoute, fcEntity *FCustomEntity) erro fcEntity.Fields = make(map[string]interface{}) if dRoute.Service != nil && dRoute.Service.ID != nil { - fcEntity.Fields["service"] = *dRoute.Service.ID + serviceMap := make(map[string]interface{}) + serviceMap["id"] = *dRoute.Service.ID + serviceMap["name"] = *dRoute.Service.Name + fcEntity.Fields["service"] = serviceMap } if dRoute.URI != nil { @@ -1024,7 +1027,7 @@ func copyToFCustomEntity(dRoute map[string]interface{}, fcEntity *FCustomEntity) dRouteFields := dRoute["fields"].(map[string]interface{}) if dRouteFields["service"] != nil { - fcEntity.Fields["service"] = kong.String(dRouteFields["service"].(string)) + fcEntity.Fields["service"] = dRouteFields["service"].(map[string]interface{}) } if dRouteFields["uri"] != nil { From 2d2ff99c1fdcba70f7e4d312b3917d31ba92de6f Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Wed, 29 Jan 2025 13:34:16 +0530 Subject: [PATCH 2/4] tests: fixed test files based on new dql-routes format; --- .../testdata/sync/037-degraphql-routes/kong-complex-query.yaml | 3 ++- tests/integration/testdata/sync/037-degraphql-routes/kong.yaml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/integration/testdata/sync/037-degraphql-routes/kong-complex-query.yaml b/tests/integration/testdata/sync/037-degraphql-routes/kong-complex-query.yaml index c3ef037..2966a38 100644 --- a/tests/integration/testdata/sync/037-degraphql-routes/kong-complex-query.yaml +++ b/tests/integration/testdata/sync/037-degraphql-routes/kong-complex-query.yaml @@ -32,4 +32,5 @@ custom_entities: author } } - service: svc1 \ No newline at end of file + service: + name: svc1 \ No newline at end of file diff --git a/tests/integration/testdata/sync/037-degraphql-routes/kong.yaml b/tests/integration/testdata/sync/037-degraphql-routes/kong.yaml index 31669aa..03b644e 100644 --- a/tests/integration/testdata/sync/037-degraphql-routes/kong.yaml +++ b/tests/integration/testdata/sync/037-degraphql-routes/kong.yaml @@ -23,4 +23,5 @@ custom_entities: fields: uri: "/foo" query: "query{ foo { bar } }" - service: svc1 \ No newline at end of file + service: + name: svc1 \ No newline at end of file From e7544a4244a52593d8e26e36c7c5c780c89c7c92 Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Wed, 29 Jan 2025 14:56:39 +0530 Subject: [PATCH 3/4] tests: fixed unit tests for file build --- pkg/file/builder_test.go | 80 ++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/pkg/file/builder_test.go b/pkg/file/builder_test.go index 8918ce4..5174b21 100644 --- a/pkg/file/builder_test.go +++ b/pkg/file/builder_test.go @@ -400,7 +400,7 @@ func existingDegraphqlRouteState(t *testing.T) *state.KongState { DegraphqlRoute: kong.DegraphqlRoute{ ID: kong.String("4bfcb11f-c962-4817-83e5-9433cf20b663"), Service: &kong.Service{ - ID: kong.String("ba54b737-38aa-49d1-87c4-64e756b0c6f9"), + ID: kong.String("fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd"), }, Methods: kong.StringSlice("GET"), URI: kong.String("/example"), @@ -3897,9 +3897,11 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { { Type: kong.String("degraphql_routes"), Fields: CustomEntityConfiguration{ - "uri": kong.String("/foo"), - "query": kong.String("query { foo { bar }}"), - "service": kong.String("fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd"), + "uri": kong.String("/foo"), + "query": kong.String("query { foo { bar }}"), + "service": map[string]interface{}{ + "id": "fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd", + }, }, }, }, @@ -3928,9 +3930,11 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { { Type: kong.String("degraphql_routes"), Fields: CustomEntityConfiguration{ - "uri": kong.String("/example"), - "query": kong.String("query{ example { foo } }"), - "service": kong.String("ba54b737-38aa-49d1-87c4-64e756b0c6f9"), + "uri": kong.String("/example"), + "query": kong.String("query{ example { foo } }"), + "service": map[string]interface{}{ + "id": "fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd", + }, }, }, }, @@ -3942,7 +3946,7 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { { ID: kong.String("4bfcb11f-c962-4817-83e5-9433cf20b663"), Service: &kong.Service{ - ID: kong.String("ba54b737-38aa-49d1-87c4-64e756b0c6f9"), + ID: kong.String("fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd"), }, Methods: kong.StringSlice("GET"), URI: kong.String("/example"), @@ -3974,7 +3978,9 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { author } }`), - "service": kong.String("foo"), + "service": map[string]interface{}{ + "name": "foo", + }, "methods": kong.StringSlice("GET", "POST"), }, }, @@ -3987,7 +3993,7 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { { ID: kong.String("dfd79b4d-7642-4b61-ba0c-9f9f0d3ba55b"), Service: &kong.Service{ - ID: kong.String("foo"), + ID: kong.String("5b1484f2-5209-49d9-b43e-92ba09dd9d52"), }, Methods: kong.StringSlice("GET", "POST"), URI: kong.String("/foo"), @@ -4028,21 +4034,37 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { name: "handles multiple degraphql routes", fields: fields{ targetContent: &Content{ + Services: []FService{ + { + Service: kong.Service{ + Name: kong.String("service1"), + }, + }, + { + Service: kong.Service{ + Name: kong.String("service2"), + }, + }, + }, CustomEntities: []FCustomEntity{ { Type: kong.String("degraphql_routes"), Fields: CustomEntityConfiguration{ - "uri": kong.String("/foo"), - "query": kong.String("query { foo }"), - "service": kong.String("service1"), + "uri": kong.String("/foo"), + "query": kong.String("query { foo }"), + "service": map[string]interface{}{ + "name": "service1", + }, }, }, { Type: kong.String("degraphql_routes"), Fields: CustomEntityConfiguration{ - "uri": kong.String("/bar"), - "query": kong.String("query { bar }"), - "service": kong.String("service2"), + "uri": kong.String("/bar"), + "query": kong.String("query { bar }"), + "service": map[string]interface{}{ + "name": "service2", + }, "methods": kong.StringSlice("POST", "PUT"), }, }, @@ -4053,24 +4075,42 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { want: &utils.KongRawState{ DegraphqlRoutes: []*kong.DegraphqlRoute{ { - ID: kong.String("0cc0d614-4c88-4535-841a-cbe0709b0758"), + ID: kong.String("9e6f82e5-4e74-4e81-a79e-4bbd6fe34cdc"), URI: kong.String("/foo"), Query: kong.String("query { foo }"), Service: &kong.Service{ - ID: kong.String("service1"), + ID: kong.String("0cc0d614-4c88-4535-841a-cbe0709b0758"), }, Methods: kong.StringSlice("GET"), }, { - ID: kong.String("083f61d3-75bc-42b4-9df4-f91929e18fda"), + ID: kong.String("ba843ee8-d63e-4c4f-be1c-ebea546d8fac"), URI: kong.String("/bar"), Query: kong.String("query { bar }"), Service: &kong.Service{ - ID: kong.String("service2"), + ID: kong.String("083f61d3-75bc-42b4-9df4-f91929e18fda"), }, Methods: kong.StringSlice("POST", "PUT"), }, }, + Services: []*kong.Service{ + { + ID: kong.String("0cc0d614-4c88-4535-841a-cbe0709b0758"), + Name: kong.String("service1"), + Protocol: kong.String("http"), + ConnectTimeout: kong.Int(60000), + WriteTimeout: kong.Int(60000), + ReadTimeout: kong.Int(60000), + }, + { + ID: kong.String("083f61d3-75bc-42b4-9df4-f91929e18fda"), + Name: kong.String("service2"), + Protocol: kong.String("http"), + ConnectTimeout: kong.Int(60000), + WriteTimeout: kong.Int(60000), + ReadTimeout: kong.Int(60000), + }, + }, }, }, { From 964496e36b25880168dcc17d7a957b36f59e092d Mon Sep 17 00:00:00 2001 From: Prashansa Kulshrestha Date: Wed, 29 Jan 2025 15:25:46 +0530 Subject: [PATCH 4/4] fix: added validations to ensure correct format for configs is passed --- pkg/file/builder_test.go | 64 +++++++++++++++++-- pkg/file/types.go | 34 ++++++++-- tests/integration/sync_test.go | 12 ++++ .../kong-wrong-svc-config.yaml | 7 ++ 4 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 tests/integration/testdata/sync/037-degraphql-routes/kong-wrong-svc-config.yaml diff --git a/pkg/file/builder_test.go b/pkg/file/builder_test.go index 5174b21..3ee2ece 100644 --- a/pkg/file/builder_test.go +++ b/pkg/file/builder_test.go @@ -3884,10 +3884,11 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { targetContent *Content } tests := []struct { - name string - fields fields - want *utils.KongRawState - wantErr bool + name string + fields fields + want *utils.KongRawState + wantErr bool + errString string }{ { name: "generates a new degraphql route from valid config passed", @@ -4114,7 +4115,53 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { }, }, { - name: "handles missing required fields", + name: "handles missing required fields - service", + fields: fields{ + targetContent: &Content{ + CustomEntities: []FCustomEntity{ + { + Type: kong.String("degraphql_routes"), + Fields: CustomEntityConfiguration{ + "uri": kong.String("/foo"), + "query": kong.String("query{ example { foo } }"), + }, + }, + }, + }, + currentState: emptyState(), + }, + want: &utils.KongRawState{ + DegraphqlRoutes: nil, + }, + wantErr: true, + errString: "service is required for degraphql_routes", + }, + { + name: "handles missing required fields - uri", + fields: fields{ + targetContent: &Content{ + CustomEntities: []FCustomEntity{ + { + Type: kong.String("degraphql_routes"), + Fields: CustomEntityConfiguration{ + "query": kong.String("query{ example { foo } }"), + "service": map[string]interface{}{ + "id": "fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd", + }, + }, + }, + }, + }, + currentState: emptyState(), + }, + want: &utils.KongRawState{ + DegraphqlRoutes: nil, + }, + wantErr: true, + errString: "uri and query are required for degraphql_routes", + }, + { + name: "handles missing required fields - uri", fields: fields{ targetContent: &Content{ CustomEntities: []FCustomEntity{ @@ -4122,6 +4169,9 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { Type: kong.String("degraphql_routes"), Fields: CustomEntityConfiguration{ "uri": kong.String("/foo"), + "service": map[string]interface{}{ + "id": "fdfd14cc-cd69-49a0-9e23-cd3375b6c0cd", + }, }, }, }, @@ -4131,7 +4181,8 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { want: &utils.KongRawState{ DegraphqlRoutes: nil, }, - wantErr: true, + wantErr: true, + errString: "uri and query are required for degraphql_routes", }, } @@ -4144,6 +4195,7 @@ func Test_stateBuilder_ingestCustomEntities(t *testing.T) { _, _, err := b.build() if tt.wantErr { require.Error(t, err, "build error was expected") + assert.ErrorContains(t, err, tt.errString) assert.Equal(t, tt.want, b.rawState) return } diff --git a/pkg/file/types.go b/pkg/file/types.go index a387b60..852ae00 100644 --- a/pkg/file/types.go +++ b/pkg/file/types.go @@ -1024,23 +1024,45 @@ func copyToFCustomEntity(dRoute map[string]interface{}, fcEntity *FCustomEntity) } fcEntity.Fields = make(map[string]interface{}) - dRouteFields := dRoute["fields"].(map[string]interface{}) + + f, ok := dRoute["fields"].(map[string]interface{}) + if !ok { + return fmt.Errorf("fields field should be a map") + } + dRouteFields := f if dRouteFields["service"] != nil { - fcEntity.Fields["service"] = dRouteFields["service"].(map[string]interface{}) + service, ok := dRouteFields["service"].(map[string]interface{}) + if !ok { + return fmt.Errorf("service field should be a map") + } + fcEntity.Fields["service"] = service } if dRouteFields["uri"] != nil { - fcEntity.Fields["uri"] = kong.String(dRouteFields["uri"].(string)) + uri, ok := dRouteFields["uri"].(string) + if !ok { + return fmt.Errorf("uri field should be a string") + } + fcEntity.Fields["uri"] = kong.String(uri) } if dRouteFields["query"] != nil { - fcEntity.Fields["query"] = kong.String(dRouteFields["query"].(string)) + query, ok := dRouteFields["query"].(string) + if !ok { + return fmt.Errorf("query field should be a string") + } + fcEntity.Fields["query"] = kong.String(query) } if dRouteFields["methods"] != nil { - methods := make([]string, len(dRouteFields["methods"].([]interface{}))) - for i, method := range dRouteFields["methods"].([]interface{}) { + methodsArray, ok := dRouteFields["methods"].([]interface{}) + if !ok { + return fmt.Errorf("methods field should be an array") + } + methods := make([]string, len(methodsArray)) + + for i, method := range methodsArray { methods[i] = method.(string) } fcEntity.Fields["methods"] = kong.StringSlice(methods...) diff --git a/tests/integration/sync_test.go b/tests/integration/sync_test.go index d5c6938..9c50770 100644 --- a/tests/integration/sync_test.go +++ b/tests/integration/sync_test.go @@ -7653,6 +7653,18 @@ func Test_Sync_DegraphqlRoutes(t *testing.T) { expectedMethods := kong.StringSlice("POST") assert.Equal(t, expectedMethods, degraphqlRoutes[0].Methods) }) + + t.Run("create degraphql route - fails if service reference is not an object", func(t *testing.T) { + err := sync("testdata/sync/037-degraphql-routes/kong-wrong-svc-config.yaml") + require.Error(t, err) + assert.ErrorContains(t, err, "service field should be a map") + }) + + t.Run("create degraphql route - fails if service reference is not an object", func(t *testing.T) { + err := sync("testdata/sync/037-degraphql-routes/kong-wrong-svc-config.yaml") + require.Error(t, err) + assert.ErrorContains(t, err, "service field should be a map") + }) } func Test_Sync_CustomEntities_Fake(t *testing.T) { diff --git a/tests/integration/testdata/sync/037-degraphql-routes/kong-wrong-svc-config.yaml b/tests/integration/testdata/sync/037-degraphql-routes/kong-wrong-svc-config.yaml new file mode 100644 index 0000000..b7f18de --- /dev/null +++ b/tests/integration/testdata/sync/037-degraphql-routes/kong-wrong-svc-config.yaml @@ -0,0 +1,7 @@ +_format_version: "3.0" +custom_entities: + - type: degraphql_routes + fields: + uri: "/foo" + query: "query{ foo { bar } }" + service: svc1 \ No newline at end of file