From 964dc71529c30c23a965668c6f3c06dc00fa7124 Mon Sep 17 00:00:00 2001 From: Martin Necas Date: Thu, 28 Mar 2024 17:36:48 +0100 Subject: [PATCH] OCM-7117 | add capability of list resource with a scalar items Issue: The LoadBalncerQuotaValues returns a list of scalar items. Because of this the metamodel started generating not valid sdk. Sample of the model: ``` resource LoadBalancerQuotaValues { method List { in out Page Integer = 1 in out Size Integer = 100 out Total Integer out Items []Integer } } ``` When generating the go sdk from teh model we get a error: ``` output/clustersmgmt/v1/load_balancer_quota_values_client.go:162:12: expected type, found '.' output/clustersmgmt/v1/load_balancer_quota_values_client.go:191:59: expected type, found '.' output/clustersmgmt/v1/load_balancer_quota_values_client.go:194:6: expected declaration, found '}' E: Can't format generated sources: exit status 2 ``` This is caused by the metamodel not handeling the list scalar items properly. Because the metamodel generates the reposnse struct and some other struct in following format: ``` type LoadBalancerQuotaValuesListResponse struct { status int header http.Header err *errors.Error items *.IntegerList page *int size *int total *int } ``` I have added a fix so it would generate the sdk structs with the list scalars. ``` // LoadBalancerQuotaValuesListResponse is the response for the 'list' method. type LoadBalancerQuotaValuesListResponse struct { status int header http.Header err *errors.Error items []int page *int size *int total *int } ``` Signed-off-by: Martin Necas --- pkg/concepts/type.go | 3 ++ pkg/generators/golang/clients_generator.go | 8 ++++- pkg/generators/golang/json_generator.go | 16 ++++++--- tests/go/clients_test.go | 24 ++++++++++++++ .../load_balancer_quota_values_resource.model | 33 +++++++++++++++++++ .../clusters_mgmt/v1/root_resource.model | 5 +++ 6 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 tests/model/clusters_mgmt/v1/load_balancer_quota_values_resource.model diff --git a/pkg/concepts/type.go b/pkg/concepts/type.go index 0ce017b..e54dee6 100644 --- a/pkg/concepts/type.go +++ b/pkg/concepts/type.go @@ -158,6 +158,9 @@ func (t *Type) IsMap() bool { // IsScalar returns true iff this type is an scalar type. Note that interface types are also considered // scalar types due to their opaque nature in the SDK. func (t *Type) IsScalar() bool { + if t == nil { + return false + } return t.kind == ScalarType || t.kind == EnumType || t.kind == InterfaceType } diff --git a/pkg/generators/golang/clients_generator.go b/pkg/generators/golang/clients_generator.go index e204b70..b9b1471 100644 --- a/pkg/generators/golang/clients_generator.go +++ b/pkg/generators/golang/clients_generator.go @@ -935,7 +935,11 @@ func (g *ClientsGenerator) generateResponseSource(method *concepts.Method) { header http.Header err *errors.Error {{ range $responseParameters }} - {{ fieldName . }} {{ fieldType . }} + {{ if and .Type.IsList .Type.Element.IsScalar }} + {{ fieldName . }} []{{ valueType .Type.Element }} + {{ else }} + {{ fieldName . }} {{ fieldType . }} + {{ end }} {{ end }} } @@ -1086,6 +1090,8 @@ func (g *ClientsGenerator) accessorType(parameter *concepts.Parameter) *TypeRefe var ref *TypeReference typ := parameter.Type() switch { + case typ.IsList() && typ.Element().IsScalar(): + ref = g.types.NullableReference(typ) case parameter.IsItems(): ref = g.types.ListReference(typ) case typ.IsScalar(): diff --git a/pkg/generators/golang/json_generator.go b/pkg/generators/golang/json_generator.go index ca8e049..018db16 100644 --- a/pkg/generators/golang/json_generator.go +++ b/pkg/generators/golang/json_generator.go @@ -979,10 +979,14 @@ func (g *JSONSupportGenerator) generateListMethodSource(method *concepts.Method) {{ end }} {{ end }} case "items": - {{ generateReadValue "items" .Items.Type false }} + {{ generateReadValue "items" .Items.Type false }} + {{ if and .Items.Type.IsList .Items.Type.Element.IsScalar }} + response.items = items + {{ else }} response.items = &{{ structName .Items.Type }}{ items: items, } + {{ end }} default: iterator.ReadAny() } @@ -1107,9 +1111,13 @@ func (g *JSONSupportGenerator) generateSearchMethodSource(method *concepts.Metho {{ end }} case "items": {{ generateReadValue "items" .Items.Type false }} - response.items = &{{ structName .Items.Type }}{ - items: items, - } + {{ if and .Items.Type.IsList .Items.Type.Element.IsScalar }} + response.items = items + {{ else }} + response.items = &{{ structName .Items.Type }}{ + items: items, + } + {{ end }} default: iterator.ReadAny() } diff --git a/tests/go/clients_test.go b/tests/go/clients_test.go index 496a9c8..3437e64 100644 --- a/tests/go/clients_test.go +++ b/tests/go/clients_test.go @@ -613,4 +613,28 @@ var _ = Describe("Client", func() { Expect(ok).To(BeTrue()) Expect(value).To(BeTrue()) }) + + It("Can get a resource list with scalar items", func() { + server.AppendHandlers(RespondWith(http.StatusOK, `{ + "kind": "LoadBalancerQuotaValueList", + "size": 5, + "page": 1, + "total": 5, + "items": [ + 1, + 2, + 3, + 4, + 5 + ] + } + `)) + client := cmv1.NewClient(transport, "/api/clusters_mgmt/v1") + response, err := client.LoadBalancerQuotaValues().List().Send() + Expect(err).ToNot(HaveOccurred()) + Expect(response).ToNot(BeNil()) + items := response.Items() + Expect(items).ToNot(BeNil()) + Expect(items[0]).To(Equal(1)) + }) }) diff --git a/tests/model/clusters_mgmt/v1/load_balancer_quota_values_resource.model b/tests/model/clusters_mgmt/v1/load_balancer_quota_values_resource.model new file mode 100644 index 0000000..42718eb --- /dev/null +++ b/tests/model/clusters_mgmt/v1/load_balancer_quota_values_resource.model @@ -0,0 +1,33 @@ +/* +Copyright (c) 2024 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Manages load balancer quota values. +resource LoadBalancerQuotaValues { + // Retrieves the list of Load Balancer Quota Values. + method List { + // Index of the requested page, where one corresponds to the first page. + in out Page Integer = 1 + + // Number of items contained in the returned page. + in out Size Integer = 100 + + // Total number of items of the collection. + out Total Integer + + // Retrieved list of values. + out Items []Integer + } +} diff --git a/tests/model/clusters_mgmt/v1/root_resource.model b/tests/model/clusters_mgmt/v1/root_resource.model index 32c8b78..fed8316 100644 --- a/tests/model/clusters_mgmt/v1/root_resource.model +++ b/tests/model/clusters_mgmt/v1/root_resource.model @@ -37,4 +37,9 @@ resource Root { locator Nil { target Nil } + + // Reference to the resource that manages the load balancer quota values. + locator LoadBalancerQuotaValues{ + target LoadBalancerQuotaValues + } }