diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 326ba3352..a8bcb7cef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,8 +13,6 @@ jobs: uses: actions/setup-go@v3 with: go-version: '>=1.17.0' - - name: setup-docker - uses: docker-practice/actions-setup-docker@1.0.11 - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@v0' - name: Build Compiler image @@ -51,8 +49,6 @@ jobs: uses: actions/setup-go@v3 with: go-version: '>=1.17.0' - - name: setup-docker - uses: docker-practice/actions-setup-docker@1.0.11 - name: Test Generate Code and Render templates run: | git config --global url."https://github.com/".insteadOf "git@github.com:" diff --git a/compiler/.gitignore b/compiler/.gitignore index 43119c410..2155e068a 100644 --- a/compiler/.gitignore +++ b/compiler/.gitignore @@ -7,6 +7,7 @@ cmd/nexus-openapi-gen cmd/gqlgen compiler.tar _generated +_tsm_temp ### GoLand ### .idea diff --git a/compiler/Dockerfile b/compiler/Dockerfile index b41fffc1f..cc7ce7b33 100644 --- a/compiler/Dockerfile +++ b/compiler/Dockerfile @@ -25,4 +25,4 @@ RUN CGO_ENABLED=0 go build --trimpath -o install.so ./cmd/validate WORKDIR /go/src/github.com/vmware-tanzu/graph-framework-for-microservices/compiler RUN go mod download -CMD make docker.gitlab_credentials && make generate_code +CMD make docker.gitlab_credentials && make preparser diff --git a/compiler/Makefile b/compiler/Makefile index 104454364..95484f0fb 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -20,6 +20,7 @@ CONFIG_FILE ?= "" GENERATED_OUTPUT_DIRECTORY ?= generated COMPILER_SRC_DIRECTORY ?= "" FORCE ?= false +PREPARSER_MODPATH ?= model NEXUS_KUBEOPENAPI_VERSION ?= 7416bd4754d3c0dd8b3fa37fff53d36594f11607 NEXUS_GRAPHQLGEN_VERSION ?= 32f028bce22efeb70b47a640195bd969dbb337f0 @@ -140,11 +141,41 @@ generate_example_in_container: test_in_container: ${BUILDER_NAME}\:${BUILDER_TAG}.image.exists $(call run_in_container, make test) +.PHONY: preparser +preparser: + @echo "Nexus Compiler: Start Preparser" + @echo "Cleaning up workdir" + rm -rf _generated + @echo "Copying generated_base_structure to create directory structure" + @echo "COMPILER_SRC_DIRECTORY: ${COMPILER_SRC_DIRECTORY}" + cp -R _generated_base_structure _generated + @echo "Cleaning up temp dir" + rm -rf _tsm_temp + @echo "Copying Datamodel to temp directory" + cp -R ${DATAMODEL_PATH} _tsm_temp + cp -R _generated_base_structure/* ${DATAMODEL_PATH}/build + @echo "Nexus Compiler: Running Preparser" + go run cmd/preparser/main.go -dsl _tsm_temp -output _generated -modpath ${PREPARSER_MODPATH} + @echo "Nexus Compiler: Remove empty directories from model directory" + @find _generated/model -depth -type d -empty -delete + + @if [ -d "_tsm_temp/global" ]; then \ + cp _tsm_temp/go.mod _tsm_temp/global/go.mod; \ + for d in _tsm_temp/*/; do \ + if [[ ! "$$d" == "_tsm_temp/global/" && ! "$$d" == "_tsm_temp/build/" ]]; then \ + cp -r "$$d" "_tsm_temp/global/"; \ + fi; \ + done; \ + $(MAKE) generate_code DATAMODEL_PATH=_tsm_temp/global; \ + else \ + $(MAKE) generate_code; \ + fi + .PHONY: generate_code generate_code: @echo "Nexus Compiler: Running compiler code generation" @echo "Cleaning up workdir" - rm -rf _generated ${GOPATH}/src/nexustempmodule + rm -rf ${GOPATH}/src/nexustempmodule @echo "Copying generated_base_structure to create directory structure" @echo "COMPILER_SRC_DIRECTORY: ${COMPILER_SRC_DIRECTORY}" cp -R _generated_base_structure _generated @@ -164,11 +195,12 @@ generate_code: @echo "Nexus Compiler: Generating CRD yamls" go run cmd/generate-openapischema/generate-openapischema.go -yamls-path _generated/crds -existing-CRDs-Path ${GENERATED_OUTPUT_DIRECTORY}/crds -force ${FORCE} git checkout -- pkg/openapi_generator/openapi/openapi_generated.go - rm -rf ${GENERATED_OUTPUT_DIRECTORY}/{client,apis,crds,common,nexus-client,helper,nexus-gql} - cp -r _generated/{client,apis,crds,common,nexus-client,helper,nexus-gql} ${GENERATED_OUTPUT_DIRECTORY} + rm -rf ${GENERATED_OUTPUT_DIRECTORY}/{client,apis,crds,common,nexus-client,helper,nexus-gql,tsm-nexus-gql,model} + cp -r _generated/{client,apis,crds,common,nexus-client,helper,nexus-gql,tsm-nexus-gql,model} ${GENERATED_OUTPUT_DIRECTORY} @echo "Nexus Compiler: Generating GRAPHQL PKG" - cd _generated && goimports -w . + cd _generated && mv model/model.go model/model.tmp && goimports -w . && mv model/model.tmp model/model.go cd _generated/nexus-gql && gqlgen generate + @echo "Nexus Compiler: GRAPHQL Generating completed" cp -rf _generated/* ${GOPATH}/src/nexustempmodule/ cd ${GOPATH}/src/nexustempmodule && cd nexus-gql && go mod init && \ go mod edit -replace nexustempmodule=${GOPATH}/src/nexustempmodule && \ @@ -180,12 +212,12 @@ generate_code: ./scripts/replace_mod_path.sh find . -name "*.bak" -type f -delete @echo "Sorting imports" - cd _generated && goimports -w . + cd _generated && mv model/model.go model/model.tmp && goimports -w . && mv model/model.tmp model/model.go @echo "Nexus Compiler: Moving files to output directory" - cp -r _generated/{client,apis,crds,common,nexus-client,helper,nexus-gql} ${GENERATED_OUTPUT_DIRECTORY} - cp -r ${GOPATH}/src/nexustempmodule/nexus-gql/graphql.so ${GENERATED_OUTPUT_DIRECTORY}/nexus-gql mkdir -p ${GENERATED_OUTPUT_DIRECTORY}/install-validator cp -r ${GOPATH}/src/github.com/vmware-tanzu/graph-framework-for-microservices/install-validator/install.so ${GENERATED_OUTPUT_DIRECTORY}/install-validator/install.so || echo "Could not find install.so file, skipping" + cp -r _generated/{client,apis,crds,common,nexus-client,helper,nexus-gql,tsm-nexus-gql,model} ${GENERATED_OUTPUT_DIRECTORY} + cp -r ${GOPATH}/src/nexustempmodule/nexus-gql/* ${GENERATED_OUTPUT_DIRECTORY}/nexus-gql/ @echo "Nexus Compiler: Compiler code generation completed" .PHONY: test_generate_code_in_container diff --git a/compiler/_generated_base_structure/model/.gitkeep b/compiler/_generated_base_structure/model/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/_generated_base_structure/tsm-nexus-gql/graph/.gitkeep b/compiler/_generated_base_structure/tsm-nexus-gql/graph/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/cmd/nexus-sdk/main.go b/compiler/cmd/nexus-sdk/main.go index 2627e8257..184f474dc 100644 --- a/compiler/cmd/nexus-sdk/main.go +++ b/compiler/cmd/nexus-sdk/main.go @@ -49,10 +49,11 @@ func main() { config.ConfigInstance = conf pkgs := parser.ParseDSLPkg(*dslDir) graphlqQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph := parser.ParseDSLNodes(*dslDir, conf.GroupName, pkgs, graphlqQueries) + graph, nonNexusTypes, fileset := parser.ParseDSLNodes(*dslDir, conf.GroupName, pkgs, graphlqQueries) methods, codes := rest.ParseResponses(pkgs) + graphqlFiles := parser.ParseGraphQLFiles(*dslDir) if err = generator.RenderCRDTemplate(conf.GroupName, conf.CrdModulePath, pkgs, graph, - *crdDir, methods, codes); err != nil { + *crdDir, methods, codes, nonNexusTypes, fileset, graphqlFiles); err != nil { log.Fatalf("Error rendering crd template: %v", err) } } diff --git a/compiler/cmd/preparser/main.go b/compiler/cmd/preparser/main.go new file mode 100644 index 000000000..16b13217a --- /dev/null +++ b/compiler/cmd/preparser/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + + log "github.com/sirupsen/logrus" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/preparser" +) + +func main() { + dslDir := flag.String("dsl", "datamodel", "DSL file location.") + outputDir := flag.String("output", "_generated", "output dir location.") + modPath := flag.String("modpath", "datamodel", "ModPath for rendered imports") + logLevel := flag.String("log-level", "ERROR", "Log level") + flag.Parse() + + lvl, err := log.ParseLevel(*logLevel) + if err != nil { + log.Fatalf("Failed to configure logging: %v\n", err) + } + log.SetLevel(lvl) + + packages := preparser.Parse(*dslDir) + err = preparser.Render(*dslDir, packages) + if err != nil { + log.Fatal(err) + } + + err = preparser.CopyPkgsToBuild(*dslDir, *outputDir) + if err != nil { + log.Fatal(err) + } + + packages = preparser.Parse(*dslDir) + err = preparser.RenderImports(packages, *outputDir, *modPath) + if err != nil { + log.Fatal(err) + } +} diff --git a/compiler/example/datamodel/config/gns/gns.go b/compiler/example/datamodel/config/gns/gns.go index ffacde4c1..970184138 100644 --- a/compiler/example/datamodel/config/gns/gns.go +++ b/compiler/example/datamodel/config/gns/gns.go @@ -4,6 +4,7 @@ import ( "net/http" cartv1 "github.com/vmware-tanzu/cartographer/pkg/apis/v1alpha1" + "k8s.io/apimachinery/pkg/util/intstr" service_group "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/example/datamodel/config/gns/service-group" policypkg "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/example/datamodel/config/policy" @@ -171,6 +172,8 @@ type Gns struct { //nexus-validation: Pattern=abc Domain string UseSharedGateway bool + Annotations string `nexus-graphql-jsonencoded:""` + TargetPort intstr.IntOrString `json:"targetPort,omitempty" mapstructure:"targetPort,omitempty"` Description Description GnsServiceGroups service_group.SvcGroup `nexus:"children"` GnsAccessControlPolicy policypkg.AccessControlPolicy `nexus:"child" nexus-graphql:"type:string"` diff --git a/compiler/example/output/_rendered_templates/apis/config.tsm.tanzu.vmware.com/v1/types.go b/compiler/example/output/_rendered_templates/apis/config.tsm.tanzu.vmware.com/v1/types.go index a5760cb96..04f5dd6b4 100644 --- a/compiler/example/output/_rendered_templates/apis/config.tsm.tanzu.vmware.com/v1/types.go +++ b/compiler/example/output/_rendered_templates/apis/config.tsm.tanzu.vmware.com/v1/types.go @@ -24,10 +24,17 @@ type Link struct { Name string `json:"name" yaml:"name"` } +// +k8s:openapi-gen=true +type SyncerStatus struct { + EtcdVersion int64 `json:"etcdVersion, omitempty" yaml:"etcdVersion, omitempty"` + CRGenerationId int64 `json:"cRGenerationId, omitempty" yaml:"cRGenerationId, omitempty"` +} + // +k8s:openapi-gen=true type NexusStatus struct { - SourceGeneration int64 `json:"sourceGeneration" yaml:"sourceGeneration"` - RemoteGeneration int64 `json:"remoteGeneration" yaml:"remoteGeneration"` + SourceGeneration int64 `json:"sourceGeneration, omitempty" yaml:"sourceGeneration, omitempty"` + RemoteGeneration int64 `json:"remoteGeneration, omitempty" yaml:"remoteGeneration, omitempty"` + SyncerStatus SyncerStatus `json:"syncerStatus, omitempty" yaml:"syncerStatus, omitempty"` } /* ------------------- CRDs definitions ------------------- */ diff --git a/compiler/example/output/_rendered_templates/apis/gns.tsm.tanzu.vmware.com/v1/types.go b/compiler/example/output/_rendered_templates/apis/gns.tsm.tanzu.vmware.com/v1/types.go index ae3ffdf01..669b6e7b3 100644 --- a/compiler/example/output/_rendered_templates/apis/gns.tsm.tanzu.vmware.com/v1/types.go +++ b/compiler/example/output/_rendered_templates/apis/gns.tsm.tanzu.vmware.com/v1/types.go @@ -23,10 +23,17 @@ type Link struct { Name string `json:"name" yaml:"name"` } +// +k8s:openapi-gen=true +type SyncerStatus struct { + EtcdVersion int64 `json:"etcdVersion, omitempty" yaml:"etcdVersion, omitempty"` + CRGenerationId int64 `json:"cRGenerationId, omitempty" yaml:"cRGenerationId, omitempty"` +} + // +k8s:openapi-gen=true type NexusStatus struct { - SourceGeneration int64 `json:"sourceGeneration" yaml:"sourceGeneration"` - RemoteGeneration int64 `json:"remoteGeneration" yaml:"remoteGeneration"` + SourceGeneration int64 `json:"sourceGeneration, omitempty" yaml:"sourceGeneration, omitempty"` + RemoteGeneration int64 `json:"remoteGeneration, omitempty" yaml:"remoteGeneration, omitempty"` + SyncerStatus SyncerStatus `json:"syncerStatus, omitempty" yaml:"syncerStatus, omitempty"` } /* ------------------- CRDs definitions ------------------- */ diff --git a/compiler/example/output/_rendered_templates/apis/policypkg.tsm.tanzu.vmware.com/v1/types.go b/compiler/example/output/_rendered_templates/apis/policypkg.tsm.tanzu.vmware.com/v1/types.go index 474e2caad..b369ca5b4 100644 --- a/compiler/example/output/_rendered_templates/apis/policypkg.tsm.tanzu.vmware.com/v1/types.go +++ b/compiler/example/output/_rendered_templates/apis/policypkg.tsm.tanzu.vmware.com/v1/types.go @@ -22,10 +22,17 @@ type Link struct { Name string `json:"name" yaml:"name"` } +// +k8s:openapi-gen=true +type SyncerStatus struct { + EtcdVersion int64 `json:"etcdVersion, omitempty" yaml:"etcdVersion, omitempty"` + CRGenerationId int64 `json:"cRGenerationId, omitempty" yaml:"cRGenerationId, omitempty"` +} + // +k8s:openapi-gen=true type NexusStatus struct { - SourceGeneration int64 `json:"sourceGeneration" yaml:"sourceGeneration"` - RemoteGeneration int64 `json:"remoteGeneration" yaml:"remoteGeneration"` + SourceGeneration int64 `json:"sourceGeneration, omitempty" yaml:"sourceGeneration, omitempty"` + RemoteGeneration int64 `json:"remoteGeneration, omitempty" yaml:"remoteGeneration, omitempty"` + SyncerStatus SyncerStatus `json:"syncerStatus, omitempty" yaml:"syncerStatus, omitempty"` } /* ------------------- CRDs definitions ------------------- */ diff --git a/compiler/example/output/_rendered_templates/apis/root.tsm.tanzu.vmware.com/v1/types.go b/compiler/example/output/_rendered_templates/apis/root.tsm.tanzu.vmware.com/v1/types.go index 112a210b0..2e8b817c8 100644 --- a/compiler/example/output/_rendered_templates/apis/root.tsm.tanzu.vmware.com/v1/types.go +++ b/compiler/example/output/_rendered_templates/apis/root.tsm.tanzu.vmware.com/v1/types.go @@ -22,10 +22,17 @@ type Link struct { Name string `json:"name" yaml:"name"` } +// +k8s:openapi-gen=true +type SyncerStatus struct { + EtcdVersion int64 `json:"etcdVersion, omitempty" yaml:"etcdVersion, omitempty"` + CRGenerationId int64 `json:"cRGenerationId, omitempty" yaml:"cRGenerationId, omitempty"` +} + // +k8s:openapi-gen=true type NexusStatus struct { - SourceGeneration int64 `json:"sourceGeneration" yaml:"sourceGeneration"` - RemoteGeneration int64 `json:"remoteGeneration" yaml:"remoteGeneration"` + SourceGeneration int64 `json:"sourceGeneration, omitempty" yaml:"sourceGeneration, omitempty"` + RemoteGeneration int64 `json:"remoteGeneration, omitempty" yaml:"remoteGeneration, omitempty"` + SyncerStatus SyncerStatus `json:"syncerStatus, omitempty" yaml:"syncerStatus, omitempty"` } /* ------------------- CRDs definitions ------------------- */ diff --git a/compiler/example/output/_rendered_templates/apis/servicegroup.tsm.tanzu.vmware.com/v1/types.go b/compiler/example/output/_rendered_templates/apis/servicegroup.tsm.tanzu.vmware.com/v1/types.go index c5cad05d7..19cebc4b3 100644 --- a/compiler/example/output/_rendered_templates/apis/servicegroup.tsm.tanzu.vmware.com/v1/types.go +++ b/compiler/example/output/_rendered_templates/apis/servicegroup.tsm.tanzu.vmware.com/v1/types.go @@ -22,10 +22,17 @@ type Link struct { Name string `json:"name" yaml:"name"` } +// +k8s:openapi-gen=true +type SyncerStatus struct { + EtcdVersion int64 `json:"etcdVersion, omitempty" yaml:"etcdVersion, omitempty"` + CRGenerationId int64 `json:"cRGenerationId, omitempty" yaml:"cRGenerationId, omitempty"` +} + // +k8s:openapi-gen=true type NexusStatus struct { - SourceGeneration int64 `json:"sourceGeneration" yaml:"sourceGeneration"` - RemoteGeneration int64 `json:"remoteGeneration" yaml:"remoteGeneration"` + SourceGeneration int64 `json:"sourceGeneration, omitempty" yaml:"sourceGeneration, omitempty"` + RemoteGeneration int64 `json:"remoteGeneration, omitempty" yaml:"remoteGeneration, omitempty"` + SyncerStatus SyncerStatus `json:"syncerStatus, omitempty" yaml:"syncerStatus, omitempty"` } /* ------------------- CRDs definitions ------------------- */ diff --git a/compiler/example/output/_rendered_templates/model/model.go b/compiler/example/output/_rendered_templates/model/model.go new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/example/output/_rendered_templates/nexus-gql/gqlgen.yml b/compiler/example/output/_rendered_templates/nexus-gql/gqlgen.yml index d37aa546e..d5e13d028 100644 --- a/compiler/example/output/_rendered_templates/nexus-gql/gqlgen.yml +++ b/compiler/example/output/_rendered_templates/nexus-gql/gqlgen.yml @@ -68,6 +68,12 @@ models: fields: PolicyConfigs: resolver: true + policypkg_ACPConfig: + fields: + DestSvcGroups: + resolver: true + SourceSvcGroups: + resolver: true policypkg_VMpolicy: fields: queryGns1: diff --git a/compiler/example/output/_rendered_templates/nexus-gql/graph/graphqlResolver.go b/compiler/example/output/_rendered_templates/nexus-gql/graph/graphqlResolver.go index 168230efc..ed1957e22 100644 --- a/compiler/example/output/_rendered_templates/nexus-gql/graph/graphqlResolver.go +++ b/compiler/example/output/_rendered_templates/nexus-gql/graph/graphqlResolver.go @@ -27,6 +27,16 @@ func getParentName(parentLabels map[string]interface{}, key string) string { return "" } +type NodeMetricTypeEnum string +type ServiceMetricTypeEnum string +type ServiceGroupByEnum string +type HTTPMethodEnum string +type EventSeverityEnum string +type AnalyticsMetricEnum string +type AnalyticsSubMetricEnum string +type TrafficDirectionEnum string +type SloDetailsEnum string + ////////////////////////////////////// // Nexus K8sAPIEndpointConfig ////////////////////////////////////// @@ -82,7 +92,7 @@ parentLabels := map[string]interface{}{"roots.root.tsm.tanzu.vmware.com":dn} return ret, nil } // Custom query -func getConfigConfigQueryExampleResolver(obj *model.ConfigConfig, StartTime *string, EndTime *string, Interval *string, IsServiceDeployment *bool, StartVal *int, ) (*model.NexusGraphqlResponse, error) { +func getConfigConfigQueryExampleResolver(obj *model.ConfigConfig, StartTime *string, EndTime *string, Interval *string, IsServiceDeployment *bool, StartVal *int,) (*model.NexusGraphqlResponse, error) { parentLabels := make(map[string]string) if obj != nil { for k, v := range obj.ParentLabels { @@ -111,7 +121,7 @@ func getConfigConfigQueryExampleResolver(obj *model.ConfigConfig, StartTime *st return resp.(*model.NexusGraphqlResponse), nil } // Custom query -func getGnsGnsqueryGns1Resolver(obj *model.GnsGns, StartTime *string, EndTime *string, Interval *string, IsServiceDeployment *bool, StartVal *int, ) (*model.NexusGraphqlResponse, error) { +func getGnsGnsqueryGns1Resolver(obj *model.GnsGns, StartTime *string, EndTime *string, Interval *string, IsServiceDeployment *bool, StartVal *int,) (*model.NexusGraphqlResponse, error) { parentLabels := make(map[string]string) if obj != nil { for k, v := range obj.ParentLabels { @@ -163,7 +173,7 @@ func getGnsGnsqueryGnsQM1Resolver(obj *model.GnsGns, ) (*model.TimeSeriesData, e return resp.(*model.TimeSeriesData), nil } // Custom query -func getGnsGnsqueryGnsQMResolver(obj *model.GnsGns, StartTime *string, EndTime *string, TimeInterval *string, SomeUserArg1 *string, SomeUserArg2 *int, SomeUserArg3 *bool, ) (*model.TimeSeriesData, error) { +func getGnsGnsqueryGnsQMResolver(obj *model.GnsGns, StartTime *string, EndTime *string, TimeInterval *string, SomeUserArg1 *string, SomeUserArg2 *int, SomeUserArg3 *bool,) (*model.TimeSeriesData, error) { parentLabels := make(map[string]string) if obj != nil { for k, v := range obj.ParentLabels { @@ -192,7 +202,7 @@ func getGnsGnsqueryGnsQMResolver(obj *model.GnsGns, StartTime *string, EndTime return resp.(*model.TimeSeriesData), nil } // Custom query -func getPolicypkgVMpolicyqueryGns1Resolver(obj *model.PolicypkgVMpolicy, StartTime *string, EndTime *string, Interval *string, IsServiceDeployment *bool, StartVal *int, ) (*model.NexusGraphqlResponse, error) { +func getPolicypkgVMpolicyqueryGns1Resolver(obj *model.PolicypkgVMpolicy, StartTime *string, EndTime *string, Interval *string, IsServiceDeployment *bool, StartVal *int,) (*model.NexusGraphqlResponse, error) { parentLabels := make(map[string]string) if obj != nil { for k, v := range obj.ParentLabels { @@ -244,7 +254,7 @@ func getPolicypkgVMpolicyqueryGnsQM1Resolver(obj *model.PolicypkgVMpolicy, ) (*m return resp.(*model.TimeSeriesData), nil } // Custom query -func getPolicypkgVMpolicyqueryGnsQMResolver(obj *model.PolicypkgVMpolicy, StartTime *string, EndTime *string, TimeInterval *string, SomeUserArg1 *string, SomeUserArg2 *int, SomeUserArg3 *bool, ) (*model.TimeSeriesData, error) { +func getPolicypkgVMpolicyqueryGnsQMResolver(obj *model.PolicypkgVMpolicy, StartTime *string, EndTime *string, TimeInterval *string, SomeUserArg1 *string, SomeUserArg2 *int, SomeUserArg3 *bool,) (*model.TimeSeriesData, error) { parentLabels := make(map[string]string) if obj != nil { for k, v := range obj.ParentLabels { @@ -1089,3 +1099,133 @@ ConditionsData := string(Conditions) return vPolicypkgACPConfigList, nil } +////////////////////////////////////// +// LINKS RESOLVER +// FieldName: DestSvcGroups Node: ACPConfig PKG: Policypkg +////////////////////////////////////// +func getPolicypkgACPConfigDestSvcGroupsResolver(obj *model.PolicypkgACPConfig, id *string) ([]*model.ServicegroupSvcGroup, error) { + log.Debugf("[getPolicypkgACPConfigDestSvcGroupsResolver]Parent Object %+v", obj) + var vServicegroupSvcGroupList []*model.ServicegroupSvcGroup + if id != nil && *id != "" { + log.Debugf("[getPolicypkgACPConfigDestSvcGroupsResolver]Id %q", *id) + vSvcGroupParent, err := nc.RootRoot().Config(getParentName(obj.ParentLabels, "configs.config.tsm.tanzu.vmware.com")).GNS(getParentName(obj.ParentLabels, "gnses.gns.tsm.tanzu.vmware.com")).GnsAccessControlPolicy(getParentName(obj.ParentLabels, "accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com")).GetPolicyConfigs(context.TODO(), getParentName(obj.ParentLabels, "acpconfigs.policypkg.tsm.tanzu.vmware.com")) + if err != nil { + log.Errorf("[getPolicypkgACPConfigDestSvcGroupsResolver]Error getting DestSvcGroups %q : %s", *id, err) + return vServicegroupSvcGroupList, nil + } + vSvcGroup, err := vSvcGroupParent.GetDestSvcGroups(context.TODO(), *id) + if err != nil { + log.Errorf("[getPolicypkgACPConfigDestSvcGroupsResolver]Error getting DestSvcGroups %q : %s", *id, err) + return vServicegroupSvcGroupList, nil + } + + for k, v := range obj.ParentLabels { + parentLabels[k] = v + } + + vServicegroupSvcGroupList = append(vServicegroupSvcGroupList, ret) + + log.Debugf("[getPolicypkgACPConfigDestSvcGroupsResolver]Output DestSvcGroups objects %v", vServicegroupSvcGroupList) + + return vServicegroupSvcGroupList, nil + } + + log.Debug("[getPolicypkgACPConfigDestSvcGroupsResolver]Id is empty, process all DestSvcGroupss") + + vSvcGroupParent, err := nc.RootRoot().Config(getParentName(obj.ParentLabels, "configs.config.tsm.tanzu.vmware.com")).GNS(getParentName(obj.ParentLabels, "gnses.gns.tsm.tanzu.vmware.com")).GnsAccessControlPolicy(getParentName(obj.ParentLabels, "accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com")).GetPolicyConfigs(context.TODO(), getParentName(obj.ParentLabels, "acpconfigs.policypkg.tsm.tanzu.vmware.com")) + if err != nil { + log.Errorf("[getPolicypkgACPConfigDestSvcGroupsResolver]Error getting parent node %s", err) + return vServicegroupSvcGroupList, nil + } + vSvcGroupAllObj, err := vSvcGroupParent.GetAllDestSvcGroups(context.TODO()) + if err != nil { + log.Errorf("[getPolicypkgACPConfigDestSvcGroupsResolver]Error getting DestSvcGroups %s", err) + return vServicegroupSvcGroupList, nil + } + for _, i := range vSvcGroupAllObj { + vSvcGroupParent, err := nc.RootRoot().Config(getParentName(obj.ParentLabels, "configs.config.tsm.tanzu.vmware.com")).GNS(getParentName(obj.ParentLabels, "gnses.gns.tsm.tanzu.vmware.com")).GnsAccessControlPolicy(getParentName(obj.ParentLabels, "accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com")).GetPolicyConfigs(context.TODO(), getParentName(obj.ParentLabels, "acpconfigs.policypkg.tsm.tanzu.vmware.com")) + if err != nil { + log.Errorf("[getPolicypkgACPConfigDestSvcGroupsResolver]Error getting parent node %s, skipping...", err) + continue + } + vSvcGroup, err := vSvcGroupParent.GetDestSvcGroups(context.TODO(), i.DisplayName()) + if err != nil { + log.Errorf("[getPolicypkgACPConfigDestSvcGroupsResolver]Error getting DestSvcGroups node %q : %s, skipping...", i.DisplayName(), err) + continue + } + + for k, v := range obj.ParentLabels { + parentLabels[k] = v + } + + vServicegroupSvcGroupList = append(vServicegroupSvcGroupList, ret) + } + log.Debugf("[getPolicypkgACPConfigDestSvcGroupsResolver]List of DestSvcGroups object %v", vServicegroupSvcGroupList) + return vServicegroupSvcGroupList, nil +} + +////////////////////////////////////// +// LINKS RESOLVER +// FieldName: SourceSvcGroups Node: ACPConfig PKG: Policypkg +////////////////////////////////////// +func getPolicypkgACPConfigSourceSvcGroupsResolver(obj *model.PolicypkgACPConfig, id *string) ([]*model.ServicegroupSvcGroup, error) { + log.Debugf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Parent Object %+v", obj) + var vServicegroupSvcGroupList []*model.ServicegroupSvcGroup + if id != nil && *id != "" { + log.Debugf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Id %q", *id) + vSvcGroupParent, err := nc.RootRoot().Config(getParentName(obj.ParentLabels, "configs.config.tsm.tanzu.vmware.com")).GNS(getParentName(obj.ParentLabels, "gnses.gns.tsm.tanzu.vmware.com")).GnsAccessControlPolicy(getParentName(obj.ParentLabels, "accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com")).GetPolicyConfigs(context.TODO(), getParentName(obj.ParentLabels, "acpconfigs.policypkg.tsm.tanzu.vmware.com")) + if err != nil { + log.Errorf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Error getting SourceSvcGroups %q : %s", *id, err) + return vServicegroupSvcGroupList, nil + } + vSvcGroup, err := vSvcGroupParent.GetSourceSvcGroups(context.TODO(), *id) + if err != nil { + log.Errorf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Error getting SourceSvcGroups %q : %s", *id, err) + return vServicegroupSvcGroupList, nil + } + + for k, v := range obj.ParentLabels { + parentLabels[k] = v + } + + vServicegroupSvcGroupList = append(vServicegroupSvcGroupList, ret) + + log.Debugf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Output SourceSvcGroups objects %v", vServicegroupSvcGroupList) + + return vServicegroupSvcGroupList, nil + } + + log.Debug("[getPolicypkgACPConfigSourceSvcGroupsResolver]Id is empty, process all SourceSvcGroupss") + + vSvcGroupParent, err := nc.RootRoot().Config(getParentName(obj.ParentLabels, "configs.config.tsm.tanzu.vmware.com")).GNS(getParentName(obj.ParentLabels, "gnses.gns.tsm.tanzu.vmware.com")).GnsAccessControlPolicy(getParentName(obj.ParentLabels, "accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com")).GetPolicyConfigs(context.TODO(), getParentName(obj.ParentLabels, "acpconfigs.policypkg.tsm.tanzu.vmware.com")) + if err != nil { + log.Errorf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Error getting parent node %s", err) + return vServicegroupSvcGroupList, nil + } + vSvcGroupAllObj, err := vSvcGroupParent.GetAllSourceSvcGroups(context.TODO()) + if err != nil { + log.Errorf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Error getting SourceSvcGroups %s", err) + return vServicegroupSvcGroupList, nil + } + for _, i := range vSvcGroupAllObj { + vSvcGroupParent, err := nc.RootRoot().Config(getParentName(obj.ParentLabels, "configs.config.tsm.tanzu.vmware.com")).GNS(getParentName(obj.ParentLabels, "gnses.gns.tsm.tanzu.vmware.com")).GnsAccessControlPolicy(getParentName(obj.ParentLabels, "accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com")).GetPolicyConfigs(context.TODO(), getParentName(obj.ParentLabels, "acpconfigs.policypkg.tsm.tanzu.vmware.com")) + if err != nil { + log.Errorf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Error getting parent node %s, skipping...", err) + continue + } + vSvcGroup, err := vSvcGroupParent.GetSourceSvcGroups(context.TODO(), i.DisplayName()) + if err != nil { + log.Errorf("[getPolicypkgACPConfigSourceSvcGroupsResolver]Error getting SourceSvcGroups node %q : %s, skipping...", i.DisplayName(), err) + continue + } + + for k, v := range obj.ParentLabels { + parentLabels[k] = v + } + + vServicegroupSvcGroupList = append(vServicegroupSvcGroupList, ret) + } + log.Debugf("[getPolicypkgACPConfigSourceSvcGroupsResolver]List of SourceSvcGroups object %v", vServicegroupSvcGroupList) + return vServicegroupSvcGroupList, nil +} + diff --git a/compiler/example/output/_rendered_templates/nexus-gql/graph/schema.graphqls b/compiler/example/output/_rendered_templates/nexus-gql/graph/schema.graphqls index dc5d49a9b..72f2153a8 100644 --- a/compiler/example/output/_rendered_templates/nexus-gql/graph/schema.graphqls +++ b/compiler/example/output/_rendered_templates/nexus-gql/graph/schema.graphqls @@ -20,7 +20,6 @@ type config_Config { IsServiceDeployment: Boolean StartVal: Int ): NexusGraphqlResponse - ACPPolicies(Id: ID): [policypkg_AccessControlPolicy!] FooExample(Id: ID): [config_FooTypeABC!] MyStr0: String @@ -73,9 +72,7 @@ type gns_Gns { Interval: String IsServiceDeployment: Boolean StartVal: Int - ): NexusGraphqlResponse - queryGnsQM1: TimeSeriesData - queryGnsQM( + ): NexusGraphqlResponse queryGnsQM1: TimeSeriesData queryGnsQM( StartTime: String EndTime: String TimeInterval: String @@ -83,7 +80,6 @@ type gns_Gns { SomeUserArg2: Int SomeUserArg3: Boolean ): TimeSeriesData - Domain: String UseSharedGateway: Boolean Description: String @@ -143,6 +139,8 @@ type policypkg_ACPConfig { Id: ID ParentLabels: Map + DestSvcGroups(Id: ID): [servicegroup_SvcGroup!] + SourceSvcGroups(Id: ID): [servicegroup_SvcGroup!] DisplayName: String Gns: String Description: String @@ -160,9 +158,7 @@ type policypkg_VMpolicy { Interval: String IsServiceDeployment: Boolean StartVal: Int - ): NexusGraphqlResponse - queryGnsQM1: TimeSeriesData - queryGnsQM( + ): NexusGraphqlResponse queryGnsQM1: TimeSeriesData queryGnsQM( StartTime: String EndTime: String TimeInterval: String @@ -170,7 +166,6 @@ type policypkg_VMpolicy { SomeUserArg2: Int SomeUserArg3: Boolean ): TimeSeriesData - } type NexusGraphqlResponse { @@ -188,3 +183,8 @@ type TimeSeriesData { Last: String TotalRecords: Int } + +directive @jsonencoded(file: String, gofile: String, name: String) on FIELD_DEFINITION +directive @relation(name: String, parameters: String, softlink: String, uuidkey: String) on FIELD_DEFINITION +directive @timeseriesAPI(file: String!, handler: String!) on FIELD_DEFINITION +directive @protobuf(file: String!, name: String!) on FIELD_DEFINITION diff --git a/compiler/example/output/_rendered_templates/tsm-nexus-gql/graph/schema.graphqls b/compiler/example/output/_rendered_templates/tsm-nexus-gql/graph/schema.graphqls new file mode 100644 index 000000000..81cbf1ef2 --- /dev/null +++ b/compiler/example/output/_rendered_templates/tsm-nexus-gql/graph/schema.graphqls @@ -0,0 +1,167 @@ + + +type root_Root @nexus(group:"root.tsm.tanzu.vmware.com",version:"v1",kind:"Root",resource:"roots",name:"Root",crdName:"roots.root.tsm.tanzu.vmware.com"){ + id: ID + config: config_Config +} + +type config_Config @nexus(group:"config.tsm.tanzu.vmware.com",version:"v1",kind:"Config",resource:"configs",name:"Config",crdName:"configs.config.tsm.tanzu.vmware.com"){ + id: ID + QueryExample( + StartTime: String + EndTime: String + Interval: String + IsServiceDeployment: Boolean + StartVal: Int + ): NexusGraphqlResponse + gNS: gns_Gns + dNS: gns_Dns + vMPPolicies: policypkg_VMpolicy + aCPPolicies(id: ID): [policypkg_AccessControlPolicy!] @relation(softlink: "true") + domain: config_Domain + fooExample(id: ID): [config_FooTypeABC!] + svcGrpInfo: servicegroup_SvcGroupLinkInfo + myStr0: String + myStr2: String + xYZPort: String @jsonencoded(gofile:"model.go", name:"Port", goname:"nexus_gns.Port") + clusterNamespaces: [] + testValMarkers: String @jsonencoded(gofile:"model.go", name:"TestValMarkers", goname:"nexus_config.TestValMarkers") + instance: Float + cuOption: String +} + +type config_FooTypeABC @nexus(group:"config.tsm.tanzu.vmware.com",version:"v1",kind:"FooTypeABC",resource:"footypeabcs",name:"FooTypeABC",crdName:"footypeabcs.config.tsm.tanzu.vmware.com"){ + id: ID + fooA: String @jsonencoded(gofile:"model.go", name:"AMap", goname:"nexus_config.AMap") + fooB: String @jsonencoded(gofile:"model.go", name:"BArray", goname:"nexus_config.BArray") + fooD: String @jsonencoded(gofile:"model.go", name:"DFloat", goname:"nexus_config.DFloat") + fooF: String @jsonencoded(gofile:"model.go", name:"DFloat", goname:"nexus_config.DFloat") +} + +type config_Domain @nexus(group:"config.tsm.tanzu.vmware.com",version:"v1",kind:"Domain",resource:"domains",name:"Domain",crdName:"domains.config.tsm.tanzu.vmware.com"){ + id: ID + pointPort: String + pointString: String + pointInt: Int + pointMap: String + pointSlice: String + sliceOfPoints: [String] + sliceOfArrPoints: [] + mapOfArrsPoints: String + pointStruct: String +} + +type gns_RandomGnsData @nexus(group:"gns.tsm.tanzu.vmware.com",version:"v1",kind:"RandomGnsData",resource:"randomgnsdatas",name:"RandomGnsData",crdName:"randomgnsdatas.gns.tsm.tanzu.vmware.com"){ + id: ID + description: String @jsonencoded(gofile:"model.go", name:"RandomDescription", goname:"nexus_gns.RandomDescription") +} + +type gns_Gns @nexus(group:"gns.tsm.tanzu.vmware.com",version:"v1",kind:"Gns",resource:"gnses",name:"Gns",crdName:"gnses.gns.tsm.tanzu.vmware.com"){ + id: ID + queryGns1( + StartTime: String + EndTime: String + Interval: String + IsServiceDeployment: Boolean + StartVal: Int + ): NexusGraphqlResponse + queryGnsQM1: TimeSeriesData @timeseriesAPI(file: "../../tsquery/timeSeriesQuery", handler: "queryGnsQM1") + queryGnsQM( + StartTime: String + EndTime: String + TimeInterval: String + SomeUserArg1: String + SomeUserArg2: Int + SomeUserArg3: Boolean + ): TimeSeriesData @timeseriesAPI(file: "../../tsquery/timeSeriesQuery", handler: "queryGnsQM") + gnsAccessControlPolicy: String + fooChild: String + domain: String + useSharedGateway: Boolean + description: String @jsonencoded(gofile:"model.go", name:"Description", goname:"nexus_gns.Description") + meta: String + port: Int + otherDescription: String + mapPointer: String + slicePointer: String + workloadSpec: String @jsonencoded(gofile:"model.go", name:"WorkloadSpec") + differentSpec: String + serviceSegmentRef: String @jsonencoded(gofile:"model.go", name:"ServiceSegmentRef", goname:"nexus_gns.ServiceSegmentRef") + serviceSegmentRefPointer: String + serviceSegmentRefs: [] + serviceSegmentRefMap: String +} + +type gns_BarChild @nexus(group:"gns.tsm.tanzu.vmware.com",version:"v1",kind:"BarChild",resource:"barchilds",name:"BarChild",crdName:"barchilds.gns.tsm.tanzu.vmware.com"){ + id: ID + name: String +} + +type gns_IgnoreChild @nexus(group:"gns.tsm.tanzu.vmware.com",version:"v1",kind:"IgnoreChild",resource:"ignorechilds",name:"IgnoreChild",crdName:"ignorechilds.gns.tsm.tanzu.vmware.com"){ + id: ID + name: String +} + +type gns_Dns @nexus(group:"gns.tsm.tanzu.vmware.com",version:"v1",kind:"Dns",resource:"dnses",name:"Dns",crdName:"dnses.gns.tsm.tanzu.vmware.com"){ + id: ID +} + +type gns_AdditionalGnsData @nexus(group:"gns.tsm.tanzu.vmware.com",version:"v1",kind:"AdditionalGnsData",resource:"additionalgnsdatas",name:"AdditionalGnsData",crdName:"additionalgnsdatas.gns.tsm.tanzu.vmware.com"){ + id: ID + description: String @jsonencoded(gofile:"model.go", name:"AdditionalDescription", goname:"nexus_gns.AdditionalDescription") +} + +type servicegroup_SvcGroupLinkInfo @nexus(group:"servicegroup.tsm.tanzu.vmware.com",version:"v1",kind:"SvcGroupLinkInfo",resource:"svcgrouplinkinfos",name:"SvcGroupLinkInfo",crdName:"svcgrouplinkinfos.servicegroup.tsm.tanzu.vmware.com"){ + id: ID + clusterName: String + domainName: String + serviceName: String + serviceType: String +} + +type policypkg_AdditionalPolicyData @nexus(group:"policypkg.tsm.tanzu.vmware.com",version:"v1",kind:"AdditionalPolicyData",resource:"additionalpolicydatas",name:"AdditionalPolicyData",crdName:"additionalpolicydatas.policypkg.tsm.tanzu.vmware.com"){ + id: ID + description: String @jsonencoded(gofile:"model.go", name:"AdditionalDescription", goname:"nexus_policy.AdditionalDescription") +} + +type policypkg_AccessControlPolicy @nexus(group:"policypkg.tsm.tanzu.vmware.com",version:"v1",kind:"AccessControlPolicy",resource:"accesscontrolpolicies",name:"AccessControlPolicy",crdName:"accesscontrolpolicies.policypkg.tsm.tanzu.vmware.com"){ + id: ID + policyConfigs(id: ID): [policypkg_ACPConfig!] +} + +type policypkg_ACPConfig @nexus(group:"policypkg.tsm.tanzu.vmware.com",version:"v1",kind:"ACPConfig",resource:"acpconfigs",name:"ACPConfig",crdName:"acpconfigs.policypkg.tsm.tanzu.vmware.com"){ + id: ID + destSvcGroups(id: ID): [servicegroup_SvcGroup!] @relation(softlink: "true") + sourceSvcGroups(id: ID): [servicegroup_SvcGroup!] @relation(softlink: "true") + displayName: String + gns: String + description: String + tags: [String] + projectId: String + conditions: [String] +} + +type policypkg_VMpolicy @nexus(group:"policypkg.tsm.tanzu.vmware.com",version:"v1",kind:"VMpolicy",resource:"vmpolicies",name:"VMpolicy",crdName:"vmpolicies.policypkg.tsm.tanzu.vmware.com"){ + id: ID + queryGns1( + StartTime: String + EndTime: String + Interval: String + IsServiceDeployment: Boolean + StartVal: Int + ): NexusGraphqlResponse + queryGnsQM1: TimeSeriesData @timeseriesAPI(file: "../../tsquery/timeSeriesQuery", handler: "queryGnsQM1") + queryGnsQM( + StartTime: String + EndTime: String + TimeInterval: String + SomeUserArg1: String + SomeUserArg2: Int + SomeUserArg3: Boolean + ): TimeSeriesData @timeseriesAPI(file: "../../tsquery/timeSeriesQuery", handler: "queryGnsQM") +} + +type policypkg_RandomPolicyData @nexus(group:"policypkg.tsm.tanzu.vmware.com",version:"v1",kind:"RandomPolicyData",resource:"randompolicydatas",name:"RandomPolicyData",crdName:"randompolicydatas.policypkg.tsm.tanzu.vmware.com"){ + id: ID + description: String @jsonencoded(gofile:"model.go", name:"RandomDescription", goname:"nexus_policy.RandomDescription") +} diff --git a/compiler/example/test-utils/output-group-name-with-hyphen-datamodel/crd_generated/tsm-nexus-gql/graph/schema.graphqls b/compiler/example/test-utils/output-group-name-with-hyphen-datamodel/crd_generated/tsm-nexus-gql/graph/schema.graphqls new file mode 100644 index 000000000..f4a368413 --- /dev/null +++ b/compiler/example/test-utils/output-group-name-with-hyphen-datamodel/crd_generated/tsm-nexus-gql/graph/schema.graphqls @@ -0,0 +1,37 @@ +schema { + query: Root +} + +type config_Config { + id: ID + fieldX: String + fieldY: Int + myStructField: String +} + +type project_Project { + id: ID + config: _Config + key: String + field1: String + field2: Int +} + +type root_Root { + id: ID + project: _Project + someRootData: String +} + +directive @jsonencoded(file: String, gofile: String, name: String) on FIELD_DEFINITION +directive @relation(name: String, parameters: String, softlink: String, uuidkey: String) on FIELD_DEFINITION +directive @timeseriesAPI(file: String!, handler: String!) on FIELD_DEFINITION +directive @protobuf(file: String!, name: String!) on FIELD_DEFINITION + +type TimeSeriesData { + Code: Int + Message: String + Data: String + Last: String + TotalRecords: Int +} diff --git a/compiler/go.mod b/compiler/go.mod index 7340c0a3d..4de5e9876 100644 --- a/compiler/go.mod +++ b/compiler/go.mod @@ -3,11 +3,15 @@ module github.com/vmware-tanzu/graph-framework-for-microservices/compiler go 1.17 require ( + github.com/elliotchance/orderedmap v1.5.0 github.com/fatih/structtag v1.2.0 github.com/ghodss/yaml v1.0.0 github.com/gogo/protobuf v1.3.2 + github.com/golang/protobuf v1.5.2 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.20.2 + github.com/onsi/gomega v1.23.0 + github.com/otiai10/copy v1.9.0 + github.com/rs/cors v1.8.3 github.com/sirupsen/logrus v1.8.1 github.com/vmware-tanzu/graph-framework-for-microservices/common-library v0.0.0-20221129104902-06818e531062 github.com/vmware-tanzu/graph-framework-for-microservices/kube-openapi v0.0.0-20220603123335-7416bd4754d3 @@ -16,7 +20,10 @@ require ( golang.org/x/text v0.7.0 golang.org/x/tools v0.1.12 k8s.io/apiextensions-apiserver v0.24.0 + k8s.io/apimachinery v0.26.0 + k8s.io/client-go v0.24.0 k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b + k8s.io/utils v0.0.0-20221107191617-1a15be271d1d ) require ( @@ -27,7 +34,6 @@ require ( github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.21.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect github.com/gonvenience/bunt v1.3.4 // indirect github.com/gonvenience/neat v1.3.11 // indirect github.com/gonvenience/term v1.0.2 // indirect @@ -37,6 +43,8 @@ require ( github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/homeport/dyff v1.5.6 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -46,8 +54,10 @@ require ( github.com/mattn/go-isatty v0.0.16 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/hashstructure v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/texttheater/golang-levenshtein v1.0.1 // indirect @@ -56,17 +66,17 @@ require ( golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apimachinery v0.24.0 // indirect - k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect - sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect + k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) replace github.com/vmware-tanzu/graph-framework-for-microservices/kube-openapi => ../kube-openapi diff --git a/compiler/go.sum b/compiler/go.sum index 6074a1f84..049ec93ea 100644 --- a/compiler/go.sum +++ b/compiler/go.sum @@ -18,24 +18,160 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= @@ -94,6 +230,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= @@ -107,6 +244,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -118,6 +256,7 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elliotchance/orderedmap v1.5.0 h1:1IsExUsjv5XNBD3ZdC7jkAAqLWOOKdbPTmkHx63OsBg= github.com/elliotchance/orderedmap v1.5.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -131,7 +270,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= @@ -218,6 +359,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonvenience/bunt v1.3.2/go.mod h1:oTOZqb1TVL1KqZm57zUCJCiwUliNfY8+d3QndOVqxpg= github.com/gonvenience/bunt v1.3.3/go.mod h1:XjlODZ8sTL9jQs9c4Kj1ZBTrHSsbUGdoRy7ROCtw8nU= github.com/gonvenience/bunt v1.3.4 h1:Row599Ohja2BPooaqd1tHYdTAKu6SWq7W/UeakTXddM= @@ -255,6 +397,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -265,6 +409,7 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -277,15 +422,29 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= @@ -307,6 +466,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -379,6 +539,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= @@ -390,6 +551,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -413,8 +575,10 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042 github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -426,9 +590,19 @@ github.com/onsi/gomega v1.18.0/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5h github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY= github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4= +github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4= +github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -467,6 +641,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= +github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -580,6 +756,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -618,6 +795,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -662,6 +841,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -670,6 +850,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= @@ -686,7 +868,18 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -698,6 +891,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -759,20 +953,36 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -796,6 +1006,7 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -855,15 +1066,22 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -885,12 +1103,39 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -934,10 +1179,68 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55 h1:U1u4KB2kx6KR/aJDjQ97hZ15wQs8ZPvDcGcRynBhkvg= +google.golang.org/genproto v0.0.0-20221018160656-63c7b68cfc55/go.mod h1:45EK0dUbEZ2NHjCeAd2LXmyjAgGUGrpGROgjhC3ADck= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -958,9 +1261,24 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -974,8 +1292,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1017,12 +1336,18 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +istio.io/api v0.0.0-20221222163824-3417dfab291b h1:wzdw9dsRO+djEP7wAa75ktLDvgEG5jraECZB5n7zfwg= +istio.io/api v0.0.0-20221222163824-3417dfab291b/go.mod h1:+IPBhFYUZBqH7ATQoxMCu1MGEbtQ+C29exvSGYGOWpI= k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= +k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I= +k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg= k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY= k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM= -k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg= +k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA= +k8s.io/client-go v0.24.0 h1:lbE4aB1gTHvYFSwm6eD3OF14NhFDKCejlnsGYlSJe5U= k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= @@ -1032,21 +1357,27 @@ k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b h1:vEhKDJESYfeRiaBNmRvO+/12RAo1c k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/compiler/pkg/generator/generator_test.go b/compiler/pkg/generator/generator_test.go index 28f11d324..a8b77c993 100644 --- a/compiler/pkg/generator/generator_test.go +++ b/compiler/pkg/generator/generator_test.go @@ -52,7 +52,7 @@ var _ = Describe("Template renderers tests", func() { pkg, ok = pkgs["github.com/vmware-tanzu/graph-framework-for-microservices/compiler/example/datamodel/config/gns"] Expect(ok).To(BeTrue()) graphqlQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + graph, _, _ := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) parentsMap = parser.CreateParentsMap(graph) Expect(parentsMap).To(HaveLen(14)) @@ -203,10 +203,9 @@ var _ = Describe("Template renderers tests", func() { pkgs := parser.ParseDSLPkg(datamodelPath) graphlqQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph := parser.ParseDSLNodes(datamodelPath, groupName, pkgs, graphlqQueries) + graph, nonNexusTypes, fileset := parser.ParseDSLNodes(datamodelPath, groupName, pkgs, graphlqQueries) methods, codes := rest.ParseResponses(pkgs) - err := generator.RenderCRDTemplate(groupName, crdModulePath, pkgs, graph, - outputDir, methods, codes) + err := generator.RenderCRDTemplate(groupName, crdModulePath, pkgs, graph, outputDir, methods, codes, nonNexusTypes, fileset, nil) Expect(err).NotTo(HaveOccurred()) }) diff --git a/compiler/pkg/generator/graphql_common.go b/compiler/pkg/generator/graphql_common.go index 707befa5c..9887d7dcd 100644 --- a/compiler/pkg/generator/graphql_common.go +++ b/compiler/pkg/generator/graphql_common.go @@ -2,14 +2,20 @@ package generator import ( "fmt" + "go/ast" + "go/types" "strconv" "strings" + "k8s.io/utils/strings/slices" + "golang.org/x/text/cases" "golang.org/x/text/language" log "github.com/sirupsen/logrus" "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/parser" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/util" + "github.com/vmware-tanzu/graph-framework-for-microservices/nexus/nexus" ) const ( @@ -25,6 +31,78 @@ const ( ` ) +type ReturnStatement struct { + Alias string + ReturnType string + FieldCount int + CRDName string + ChainAPI string + IsSingleton bool +} + +type FieldProperty struct { + IsResolver bool + IsNexusTypeField bool + IsNexusOrSingletonField bool + IsChildOrLink bool + IsChildrenOrLinks bool + IsMapTypeField bool + IsArrayTypeField bool + IsStdTypeField bool + IsCustomTypeField bool + IsPointerTypeField bool + IsStringType bool + IsArrayStdType bool + IsSingleton bool + PkgName string + NodeName string + FieldName string + FieldType string + FieldTypePkgPath string + ModelType string + SchemaFieldName string + SchemaTypeName string + BaseTypeName string + Alias string + ReturnType string + FieldCount int + CRDName string + ChainAPI string + LinkAPI string +} + +type NodeProperty struct { + IsParentNode bool + HasParent bool + IsSingletonNode bool + IsNexusNode bool + BaseImportPath string + CrdName string + ResolverCount int + PkgName string + NodeName string + SchemaName string + Alias string + ReturnType string + GroupResourceNameTitle string + GroupName string + Singular string + Kind string + ResourceName string + ResourceVersion string + ChildFields []FieldProperty + LinkFields []FieldProperty + ChildrenFields []FieldProperty + LinksFields []FieldProperty + ArrayFields []FieldProperty + CustomFields []FieldProperty + NonStructFields []FieldProperty + GraphqlSchemaFields []FieldProperty + ResolverFields map[string][]FieldProperty + CustomQueries []nexus.GraphQLQuery + GraphQlSpec nexus.GraphQLSpec +} + // Convert go standardType to GraphQL standardType func convertGraphqlStdType(t string) string { // remove pointers @@ -55,6 +133,14 @@ func getPkgName(pkgs parser.Packages, pkgPath string) string { return pkgs[importPath].Name } +func GetPkg(pkgs parser.Packages, pkgPath string) parser.Package { + importPath, err := strconv.Unquote(pkgPath) + if err != nil { + log.Errorf("Failed to parse the package path : %s: %v", pkgPath, err) + } + return pkgs[importPath] +} + func genSchemaResolverName(fn1, fn2 string) (string, string) { return fmt.Sprintf("%s_%s", strings.ToLower(fn1), fn2), cases.Title(language.Und, cases.NoLower).String(fn1) + cases.Title(language.Und, cases.NoLower).String(fn2) } @@ -80,6 +166,44 @@ func ValidateImportPkg(pkgName, typeString string, importMap map[string]string, return genSchemaResolverName(pkgName, typeWithoutPointers) } +func GetNexusSchemaFieldName(GraphQlSpec nexus.GraphQLSpec) string { + name := "id" + value := "ID" + if GraphQlSpec.IdName != "" { + name = GraphQlSpec.IdName + } + if !GraphQlSpec.IdNullable { + value = "ID!" + } + return fmt.Sprintf("%s: %s", name, value) +} + +func GetNodeDetails(pkgName, typeString string, importMap map[string]string, pkgs parser.Packages, gqlSpecMap map[string]nexus.GraphQLSpec) string { + typeWithoutPointers := strings.ReplaceAll(typeString, "*", "") + if strings.Contains(typeWithoutPointers, ".") { + part := strings.Split(typeWithoutPointers, ".") + if val, ok := importMap[part[0]]; ok { + p := GetPkg(pkgs, val) + if val, ok := parser.GetNexusGraphqlSpecAnnotation(p, part[1]); ok { + gqlspec := gqlSpecMap[fmt.Sprintf("%s.%s", p.Name, val)] + return GetNexusSchemaFieldName(gqlspec) + } + } + for _, v := range importMap { + pkgName := getPkgName(pkgs, v) + if pkgName == part[0] { + p := GetPkg(pkgs, v) + if val, ok := parser.GetNexusGraphqlSpecAnnotation(p, part[1]); ok { + gqlspec := gqlSpecMap[fmt.Sprintf("%s.%s", p.Name, val)] + return GetNexusSchemaFieldName(gqlspec) + } + } + } + return fmt.Sprintf("id: ID") + } + return fmt.Sprintf("id: ID") +} + func getBaseNodeType(typeString string) string { if strings.Contains(typeString, ".") { part := strings.Split(typeString, ".") @@ -87,3 +211,284 @@ func getBaseNodeType(typeString string) string { } return typeString } + +func constructNexusTypeMap(nodes []*NodeProperty) map[string]string { + crdNameMap := make(map[string]string) + for _, n := range nodes { + if n.IsNexusNode || n.IsSingletonNode { + crdNameMap[n.CrdName] = n.PkgName + n.NodeName + } + } + return crdNameMap +} + +func findTypeAndPkgForField(ptParts []string, importMap map[string]string, pkgs map[string]parser.Package) (string, *parser.Package) { + structPkg := ptParts[0] + structType := ptParts[1] + + pkgPath, ok := importMap[structPkg] + if !ok { + log.Errorf("Cannot find the package name %s for the type %s", structPkg, structType) + return "", nil + } + + importPath, err := strconv.Unquote(pkgPath) + if err != nil { + log.Errorf("Failed to parse package %s for the type %s with error %v", pkgPath, structType, err) + return "", nil + } + + p, ok := pkgs[importPath] + if !ok { + log.Errorf("Cannot find the package details from the path %s for the type %s", importPath, structType) + return "", nil + } + + return structType, &p +} + +/* +collect and construct type alias field into map recursively before +populating the nexus node and custom struct type +ex. nonStructMap[pkgName] = nodeType --> nonStructMap["root"] = "AliasTypeFoo" +*/ +func constructAliasType(sortedPackages []parser.Package) map[string]string { + nonStructMap := make(map[string]string) + for _, pkg := range sortedPackages { + for _, node := range pkg.GetNonStructTypes() { + pkgName := fmt.Sprintf("%s_%s", pkg.Name, parser.GetTypeName(node)) + // NonStruct Map + nonStructType := types.ExprString(node.Type) + nonStructMap[pkgName] = nonStructType + } + } + + return nonStructMap +} + +func setNexusProperties(nodeHelper parser.NodeHelper, node *ast.TypeSpec, nodeProp *NodeProperty) { + if len(nodeHelper.Parents) > 0 { + nodeProp.HasParent = true + } + + if parser.IsSingletonNode(node) { + nodeProp.IsSingletonNode = true + } + + if parser.IsNexusNode(node) { + nodeProp.IsNexusNode = true + } +} + +// isRootOfGraph intended to allow only one root of the graph, +// if we receive multiple node in such behaviour, then we allow the first node and the rest will be skipped with error +// arg: `parents` indicates the node's parents, `rootOfGraph` indicates if the received node is the root of the graph or not. +func isRootOfGraph(parents []string, rootOfGraph bool) bool { + if len(parents) == 0 && !rootOfGraph { + return true + } + + return rootOfGraph +} + +func getGraphqlSchemaName(pattern, fieldName, schemaType string, f *ast.Field) string { + schemaName := fmt.Sprintf(pattern, fieldName, schemaType) + schemaType = strings.TrimPrefix(schemaType, "global_") + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_ALIAS_TYPE_ANNOTATION) { + schemaType = parser.GetFieldAnnotationVal(f, parser.GRAPHQL_ALIAS_TYPE_ANNOTATION) + } + if fieldName != "" { + // use camelCase for fieldName #e.g ServiceGroup --> serviceGroup + schemaName = fmt.Sprintf(pattern, getAliasFieldValue(fieldName, f), schemaType) + } + + schemaName = strings.TrimPrefix(schemaName, "global_") + + return schemaName +} + +// func getGraphQLArgs(f *ast.Field) string { +// argKey := "id" +// argVal := "ID" +// k := parser.GetGraphqlArgumentKey(f) +// if k != "" { +// argKey = k +// } +// v := parser.GetGraphqlArgumentValue(f) +// if v != "" { +// argVal = v +// } +// return fmt.Sprintf("%s: %s", argKey, argVal) +// } + +// getTsmGraphqlSchemaFieldName process nexus annotation `nexus-graphql-nullable` and `nexus-graphql-tsm-directive` +func getTsmGraphqlSchemaFieldName(sType GraphQLSchemaType, fieldName, schemaType, listArg string, f *ast.Field, pkg parser.Package, nonNexusTypes *parser.NonNexusTypes) string { + pattern := "" + nullable := parser.IsNexusGraphqlNullField(f) + jsonEncoded := parser.IsJsonStringField(f) + switch sType { + case Standard, JsonMarshal, Child, Link: + if nullable { + pattern = "%s: %s" + } else { + pattern = "%s: %s!" + } + if jsonEncoded { + pattern = "%s: %s" + schemaType = "String" + } + case Array: + if nullable { + pattern = "%s: [%s]" + } else { + pattern = "%s: [%s!]" + } + if jsonEncoded { + pattern = "%s: %s" + schemaType = "String" + } + case NamedChild, NamedLink: + if nullable { + pattern = "%s(" + listArg + "): [%s!]" + } else { + pattern = "%s(" + listArg + "): [%s]" + } + if jsonEncoded { + pattern = "%s(" + listArg + "): %s" + schemaType = "String" + } + } + schemaName := getGraphqlSchemaName(pattern, fieldName, schemaType, f) + + if sType == AliasType { + e := parser.GetFieldAnnotationVal(f, parser.GRAPHQL_ALIAS_TYPE_ANNOTATION) + if e != "" { + schemaName = fmt.Sprintf("%s: %s", getAliasFieldValue(fieldName, f), e) + } else { + schemaName = fmt.Sprintf("%s: %s", getAliasFieldValue(fieldName, f), "String") + } + } + + schemaName = addFieldAnnotations(pkg, f, schemaName, sType, nonNexusTypes) + + return schemaName +} + +func addFieldAnnotations(pkg parser.Package, f *ast.Field, schemaName string, sType GraphQLSchemaType, nonNexusTypes *parser.NonNexusTypes) string { + importMap := pkg.GetImportMap() + // add jsonencoded annotation + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_TSM_DIRECTIVE_ANNOTATION) { + replacer := strings.NewReplacer("nexus-graphql-tsm-directive:", "", "\\", "") + out := replacer.Replace(parser.GetFieldAnnotationString(f, parser.GRAPHQL_TSM_DIRECTIVE_ANNOTATION)) + schemaName += " " + strings.Trim(out, "\"") + } else if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_PROTOBUF_NAME) || + parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_PROTOBUF_FILE) { + schemaName = addProtobufAnnotation(f, schemaName) + } else { + if sType != Link && sType != Child && sType != NamedChild && sType != NamedLink { + if val, ok := f.Type.(*ast.SelectorExpr); ok { + x := types.ExprString(val.X) + if imp, ok := importMap[x]; ok { + if strings.HasPrefix(imp, fmt.Sprintf(`"%s`, pkg.ModPath)) { + schemaName = addJsonencodedAnnotation(f, parser.GRAPHQL_TS_TYPE_ANNOTATION, x, val.Sel.Name, schemaName, false, imp) + } else { + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_TYPE_NAME) { + typeName := parser.GetFieldAnnotationVal(f, parser.GRAPHQL_TYPE_NAME) + externalType := fmt.Sprintf("%s.%s", x, val.Sel.Name) + aliasType := fmt.Sprintf("type %s %s", typeName, externalType) + if !slices.Contains(nonNexusTypes.ExternalTypes, aliasType) { + nonNexusTypes.ExternalTypes = append(nonNexusTypes.ExternalTypes, aliasType) + } + schemaName = addJsonencodedAnnotation(f, parser.GRAPHQL_TS_TYPE_ANNOTATION, x, typeName, schemaName, true, imp) + } else { + schemaName = addJsonencodedAnnotation(f, parser.GRAPHQL_TS_TYPE_ANNOTATION, x, val.Sel.Name, schemaName, true, imp) + } + } + } + } else if val, ok := f.Type.(*ast.Ident); ok && convertGraphqlStdType(val.Name) == "" { + x := "" + importExpr := "" + if pkg.Name != "global" { + x = pkg.Name + importExpr = fmt.Sprintf(`"%s"`, pkg.FullName) + } + schemaName = addJsonencodedAnnotation(f, parser.GRAPHQL_TS_TYPE_ANNOTATION, x, val.Name, schemaName, false, importExpr) + } else if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_JSONENCODED_ANNOTATION) { + schemaName += " @jsonencoded" + } + } + + schemaName = addRelationAnnotation(sType, f, schemaName) + } + + return schemaName +} + +func addJsonencodedAnnotation(f *ast.Field, annotation parser.FieldAnnotation, x string, name string, schemaName string, external bool, importExpr string) string { + args := []string{`gofile:"model.go"`, fmt.Sprintf(`name:"%s"`, name)} + + if parser.IsFieldAnnotationPresent(f, annotation) { + args = append(args, fmt.Sprintf(`file:"%s"`, parser.GetFieldAnnotationVal(f, annotation))) + } + + if !external && x != "" { + importStr := strings.Trim(importExpr, "\"") + namedImport := "nexus_" + importStr[strings.LastIndex(importStr, "/")+1:] + args = append(args, fmt.Sprintf(`goname:"%s.%s"`, namedImport, name)) + } + + schemaName += fmt.Sprintf(" @jsonencoded(%s)", strings.Join(args, ", ")) + + return schemaName +} + +func addRelationAnnotation(sType GraphQLSchemaType, f *ast.Field, schemaName string) string { + var args []string + if sType == Link || sType == NamedLink { + args = append(args, `softlink: "true"`) + } + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_RELATION_NAME) { + args = append(args, fmt.Sprintf(`name:"%s"`, parser.GetFieldAnnotationVal(f, parser.GRAPHQL_RELATION_NAME))) + } + + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_RELATION_PARAMETERS) { + args = append(args, fmt.Sprintf("parameters:%s", parser.GetFieldAnnotationVal(f, parser.GRAPHQL_RELATION_PARAMETERS))) + } + + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_RELATION_UUIDKEY) { + args = append(args, fmt.Sprintf(`uuidkey:"%s"`, parser.GetFieldAnnotationVal(f, parser.GRAPHQL_RELATION_UUIDKEY))) + } + + if len(args) > 0 { + schemaName += fmt.Sprintf(" @relation(%s)", strings.Join(args, ", ")) + } + + return schemaName +} + +func addProtobufAnnotation(f *ast.Field, schemaName string) string { + var args []string + + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_PROTOBUF_NAME) { + args = append(args, fmt.Sprintf(`name:"%s"`, parser.GetFieldAnnotationVal(f, parser.GRAPHQL_PROTOBUF_NAME))) + } + + if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_PROTOBUF_FILE) { + args = append(args, fmt.Sprintf(`file:"%s"`, parser.GetFieldAnnotationVal(f, parser.GRAPHQL_PROTOBUF_FILE))) + } + + if len(args) > 0 { + schemaName += fmt.Sprintf(" @protobuf(%s)", strings.Join(args, ", ")) + } + + return schemaName +} + +// getAliasFieldValue process nexus annotation `nexus-alias-value:` +func getAliasFieldValue(fieldName string, f *ast.Field) string { + e := parser.GetFieldAnnotationVal(f, parser.GRAPHQL_ALIAS_NAME_ANNOTATION) + if e != "" { + return e + } + return util.GetTag(fieldName) +} diff --git a/compiler/pkg/generator/graphql_custom_query_generator.go b/compiler/pkg/generator/graphql_custom_query_generator.go index cba5336af..f89dcd4d8 100644 --- a/compiler/pkg/generator/graphql_custom_query_generator.go +++ b/compiler/pkg/generator/graphql_custom_query_generator.go @@ -17,6 +17,10 @@ func CustomQueryToGraphqlSchema(query nexus.GraphQLQuery) string { args = "(\n" for _, arg := range argsList { graphqlType := convertGraphqlStdType(arg.Type) + // AliasType is to over write arg type with annotation `nexus-alias-type:""` + if arg.AliasType { + graphqlType = arg.Type + } if graphqlType == "" { log.Fatalf("Failed to convert type %s to graphql types, supported types are: "+ "string, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, "+ @@ -38,5 +42,5 @@ func CustomQueryToGraphqlSchema(query nexus.GraphQLQuery) string { log.Fatalf("Wrong Api Type of Graphql custom query") } - return fmt.Sprintf(" %s"+args+": "+returnType+"\n", query.Name) + return fmt.Sprintf(" %s"+args+": "+returnType, query.Name) } diff --git a/compiler/pkg/generator/graphql_custom_query_generator_test.go b/compiler/pkg/generator/graphql_custom_query_generator_test.go index 2d17a27fc..dde507587 100644 --- a/compiler/pkg/generator/graphql_custom_query_generator_test.go +++ b/compiler/pkg/generator/graphql_custom_query_generator_test.go @@ -17,7 +17,7 @@ var _ = Describe("Graphql Custom query generator tests", func() { BeforeEach(func() { pkgs = parser.ParseDSLPkg(exampleDSLPath) graphqlQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + graph, _, _ := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) root, ok := graph["roots.root.tsm.tanzu.vmware.com"] Expect(ok).To(BeTrue()) config, ok := root.SingleChildren["Config"] @@ -27,7 +27,7 @@ var _ = Describe("Graphql Custom query generator tests", func() { }) It("should translate graphql query spec to schema", func() { - schema := generator.CustomQueryToGraphqlSchema(gns.GraphqlSpec.Queries[0]) + schema := generator.CustomQueryToGraphqlSchema(gns.GraphqlQuerySpec.Queries[0]) Expect(schema).To(Equal(` queryGns1( StartTime: String EndTime: String @@ -36,7 +36,7 @@ var _ = Describe("Graphql Custom query generator tests", func() { StartVal: Int ): NexusGraphqlResponse `)) - schema = generator.CustomQueryToGraphqlSchema(gns.GraphqlSpec.Queries[1]) + schema = generator.CustomQueryToGraphqlSchema(gns.GraphqlQuerySpec.Queries[1]) Expect(schema).To(Equal(` queryGnsQM1: TimeSeriesData `)) }) diff --git a/compiler/pkg/generator/resolver_generator.go b/compiler/pkg/generator/resolver_generator.go index fa0824c6e..4cde13c5f 100644 --- a/compiler/pkg/generator/resolver_generator.go +++ b/compiler/pkg/generator/resolver_generator.go @@ -3,84 +3,15 @@ package generator import ( "fmt" "go/ast" - "go/types" "sort" - "strconv" "strings" log "github.com/sirupsen/logrus" "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/parser" "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/util" - "github.com/vmware-tanzu/graph-framework-for-microservices/nexus/nexus" ) -type ReturnStatement struct { - Alias string - ReturnType string - FieldCount int - CRDName string - ChainAPI string - IsSingleton bool -} - -type FieldProperty struct { - IsResolver bool - IsNexusTypeField bool - IsNexusOrSingletonField bool - IsChildOrLink bool - IsChildrenOrLinks bool - IsMapTypeField bool - IsArrayTypeField bool - IsStdTypeField bool - IsCustomTypeField bool - IsPointerTypeField bool - IsStringType bool - IsArrayStdType bool - IsSingleton bool - PkgName string - NodeName string - FieldName string - FieldType string - FieldTypePkgPath string - ModelType string - SchemaFieldName string - SchemaTypeName string - BaseTypeName string - Alias string - ReturnType string - FieldCount int - CRDName string - ChainAPI string - LinkAPI string -} - -type NodeProperty struct { - IsParentNode bool - HasParent bool - IsSingletonNode bool - IsNexusNode bool - BaseImportPath string - CrdName string - ResolverCount int - PkgName string - NodeName string - SchemaName string - Alias string - ReturnType string - GroupResourceNameTitle string - ChildFields []FieldProperty - LinkFields []FieldProperty - ChildrenFields []FieldProperty - LinksFields []FieldProperty - ArrayFields []FieldProperty - CustomFields []FieldProperty - NonStructFields []FieldProperty - GraphqlSchemaFields []FieldProperty - ResolverFields map[string][]FieldProperty - CustomQueries []nexus.GraphQLQuery -} - // populateValuesForEachNode populates each node with required resolver properties func populateValuesForEachNode(nodes []*NodeProperty, linkAPI map[string]string, retMap map[string]ReturnStatement) []NodeProperty { var nodeProperties []NodeProperty @@ -259,16 +190,6 @@ func populateValuesForResolver(nodes []*NodeProperty, parentsMap map[string]pars return linkAPI, retMap } -func constructNexusTypeMap(nodes []*NodeProperty) map[string]string { - crdNameMap := make(map[string]string) - for _, n := range nodes { - if n.IsNexusNode || n.IsSingletonNode { - crdNameMap[n.CrdName] = n.PkgName + n.NodeName - } - } - return crdNameMap -} - // processNonNexusFields process and populates properties for each non nexus fields // func processNonNexusFields(aliasNameMap map[string]string, node *ast.TypeSpec, @@ -295,7 +216,7 @@ func processNonNexusFields(aliasNameMap map[string]string, node *ast.TypeSpec, continue } - if parser.IsJsonStringField(f) { + if parser.IsJsonStringField(f) || parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_JSONENCODED_ANNOTATION) { fieldProp.IsStringType = true fieldProp.SchemaFieldName = fmt.Sprintf("%s: %s", fieldProp.FieldName, "String") resField[nodeProp.PkgName+nodeProp.NodeName] = append(resField[nodeProp.PkgName+nodeProp.NodeName], fieldProp) @@ -317,38 +238,6 @@ func processNonNexusFields(aliasNameMap map[string]string, node *ast.TypeSpec, } } -func findTypeAndPkgForField(ptParts []string, importMap map[string]string, pkgs map[string]parser.Package) (string, *parser.Package) { - structPkg := ptParts[0] - structType := ptParts[1] - - // if the import path has alias name, it is resolved - importPath, ok := importMap[structPkg] - if !ok { - // when pkg and directory names are different and no alias name provided, - // try to resolve by package name - for _, path := range importMap { - pkgName := getPkgName(pkgs, path) - if pkgName == structPkg { - importPath = path - } - } - } - - pkgPath, err := strconv.Unquote(importPath) - if err != nil { - log.Errorf("Failed to parse package %s for the type %s with error %v", pkgPath, structType, err) - return "", nil - } - - p, ok := pkgs[pkgPath] - if !ok { - log.Errorf("Cannot find the package details from the path %s for the type %s", importPath, structType) - return "", nil - } - - return structType, &p -} - // SkipSecretSpecAnnotation checks if the field has nexus secrets annotated on them // If yes, the field is skipped in the response. func SkipSecretSpecAnnotation(fieldName, nfType string, pkg parser.Package, importMap map[string]string, pkgs map[string]parser.Package) bool { @@ -477,50 +366,6 @@ func processNexusFields(pkg parser.Package, aliasNameMap map[string]string, node } } -/* -collect and construct type alias field into map recursively before -populating the nexus node and custom struct type -ex. nonStructMap[pkgName] = nodeType --> nonStructMap["root"] = "AliasTypeFoo" -*/ -func constructAliasType(sortedPackages []parser.Package) map[string]string { - nonStructMap := make(map[string]string) - for _, pkg := range sortedPackages { - for _, node := range pkg.GetNonStructTypes() { - pkgName := fmt.Sprintf("%s_%s", pkg.Name, parser.GetTypeName(node)) - // NonStruct Map - nonStructType := types.ExprString(node.Type) - nonStructMap[pkgName] = nonStructType - } - } - - return nonStructMap -} - -func setNexusProperties(nodeHelper parser.NodeHelper, node *ast.TypeSpec, nodeProp *NodeProperty) { - if len(nodeHelper.Parents) > 0 { - nodeProp.HasParent = true - } - - if parser.IsSingletonNode(node) { - nodeProp.IsSingletonNode = true - } - - if parser.IsNexusNode(node) { - nodeProp.IsNexusNode = true - } -} - -// isRootOfGraph intended to allow only one root of the graph, -// if we receive multiple node in such behaviour, then we allow the first node and the rest will be skipped with error -// arg: `parents` indicates the node's parents, `rootOfGraph` indicates if the received node is the root of the graph or not. -func isRootOfGraph(parents []string, rootOfGraph bool) bool { - if len(parents) == 0 && !rootOfGraph { - return true - } - - return rootOfGraph -} - // GenerateGraphqlResolverVars populates the node and its field properties required to generate graphql resolver func GenerateGraphqlResolverVars(baseGroupName, crdModulePath string, pkgs parser.Packages, parentsMap map[string]parser.NodeHelper) ([]NodeProperty, error) { sortedKeys := make([]string, 0, len(pkgs)) @@ -561,7 +406,7 @@ func GenerateGraphqlResolverVars(baseGroupName, crdModulePath string, pkgs parse nodeProp.CrdName = util.GetCrdName(node.Name.String(), pkg.Name, baseGroupName) nodeHelper := parentsMap[nodeProp.CrdName] nodeProp.IsParentNode = parser.IsNexusNode(node) - nodeProp.CustomQueries = nodeHelper.GraphqlSpec.Queries + nodeProp.CustomQueries = nodeHelper.GraphqlQuerySpec.Queries if parser.IsNexusNode(node) && len(nodeHelper.Parents) == 0 && rootOfGraph { log.Errorf("Can't allow multiple root of the graph, skipping Node:%s", nodeProp.NodeName) diff --git a/compiler/pkg/generator/resolver_generator_test.go b/compiler/pkg/generator/resolver_generator_test.go index 5490e2302..03c8cd7c7 100644 --- a/compiler/pkg/generator/resolver_generator_test.go +++ b/compiler/pkg/generator/resolver_generator_test.go @@ -21,7 +21,7 @@ var _ = Describe("Template renderers tests", func() { config.ConfigInstance.IgnoredDirs = []string{"ignored"} pkgs = parser.ParseDSLPkg(exampleDSLPath) graphqlQueries = parser.ParseGraphqlQuerySpecs(pkgs) - graph := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + graph, _, _ := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) parentsMap = parser.CreateParentsMap(graph) }) @@ -53,7 +53,7 @@ var _ = Describe("Template renderers tests", func() { It("should resolve non-singleton root and singleton child node", func() { pkgs = parser.ParseDSLPkg("../../example/test-utils/non-singleton-root") - graph := parser.ParseDSLNodes("../../example/test-utils/non-singleton-root", baseGroupName, pkgs, graphqlQueries) + graph, _, _ := parser.ParseDSLNodes("../../example/test-utils/non-singleton-root", baseGroupName, pkgs, graphqlQueries) parentsMap = parser.CreateParentsMap(graph) vars, err := generator.GenerateGraphqlResolverVars(baseGroupName, crdModulePath, pkgs, parentsMap) diff --git a/compiler/pkg/generator/template/graphql/graphqlResolver.go.tmpl b/compiler/pkg/generator/template/graphql/graphqlResolver.go.tmpl index 1e99f8178..166f139de 100644 --- a/compiler/pkg/generator/template/graphql/graphqlResolver.go.tmpl +++ b/compiler/pkg/generator/template/graphql/graphqlResolver.go.tmpl @@ -27,6 +27,16 @@ func getParentName(parentLabels map[string]interface{}, key string) string { return "" } +type NodeMetricTypeEnum string +type ServiceMetricTypeEnum string +type ServiceGroupByEnum string +type HTTPMethodEnum string +type EventSeverityEnum string +type AnalyticsMetricEnum string +type AnalyticsSubMetricEnum string +type TrafficDirectionEnum string +type SloDetailsEnum string + ////////////////////////////////////// // Nexus K8sAPIEndpointConfig ////////////////////////////////////// @@ -135,7 +145,7 @@ func getRootResolver(id *string) ([]*model.{{$node.PkgName}}{{$node.NodeName}}, {{ end }}{{end}} {{- range $key, $query := $node.CustomQueries }} // Custom query -func get{{$node.PkgName}}{{$node.NodeName}}{{$query.Name}}Resolver(obj *model.{{$node.PkgName}}{{$node.NodeName}}, {{ range $key, $arg := $query.Args }} {{$arg.Name}} *{{$arg.Type}}, {{ end }}) ({{- if eq $query.ApiType 0 }}*model.NexusGraphqlResponse{{- else if eq $query.ApiType 1 }}*model.TimeSeriesData {{- end}}, error) { +func get{{$node.PkgName}}{{$node.NodeName}}{{$query.Name}}Resolver(obj *model.{{$node.PkgName}}{{$node.NodeName}}, {{ range $key, $arg := $query.Args }} {{- if $arg.AliasType }} {{$arg.Name}} *model.{{$arg.Type}}, {{- else }} {{$arg.Name}} *{{$arg.Type}}, {{- end}}{{ end }}) ({{- if eq $query.ApiType 0 }}*model.NexusGraphqlResponse{{- else if eq $query.ApiType 1 }}*model.TimeSeriesData {{- end}}, error) { parentLabels := make(map[string]string) if obj != nil { for k, v := range obj.ParentLabels { diff --git a/compiler/pkg/generator/template/graphql/schema.graphqls.tmpl b/compiler/pkg/generator/template/graphql/schema.graphqls.tmpl index a614e1956..755cc8dd0 100644 --- a/compiler/pkg/generator/template/graphql/schema.graphqls.tmpl +++ b/compiler/pkg/generator/template/graphql/schema.graphqls.tmpl @@ -35,3 +35,14 @@ type TimeSeriesData { Last: String TotalRecords: Int } + +{{- range $key, $val := .GraphQlFiles}} + {{- if eq $key "_tsm_temp/global/common/enums.graphql" }} + {{ $val }} + {{- else}}{{ end }} +{{- end }} + +directive @jsonencoded(file: String, gofile: String, name: String) on FIELD_DEFINITION +directive @relation(name: String, parameters: String, softlink: String, uuidkey: String) on FIELD_DEFINITION +directive @timeseriesAPI(file: String!, handler: String!) on FIELD_DEFINITION +directive @protobuf(file: String!, name: String!) on FIELD_DEFINITION diff --git a/compiler/pkg/generator/template/model.go.tmpl b/compiler/pkg/generator/template/model.go.tmpl new file mode 100644 index 000000000..8fc992aa7 --- /dev/null +++ b/compiler/pkg/generator/template/model.go.tmpl @@ -0,0 +1 @@ +{{.Types}} \ No newline at end of file diff --git a/compiler/pkg/generator/template/tsm-graphql/schema.graphqls.tmpl b/compiler/pkg/generator/template/tsm-graphql/schema.graphqls.tmpl new file mode 100644 index 000000000..8ce8642fe --- /dev/null +++ b/compiler/pkg/generator/template/tsm-graphql/schema.graphqls.tmpl @@ -0,0 +1,15 @@ +{{- range $key, $node := .Nodes }} +{{- if $node.IsNexusNode }} +{{ $length := len $node.GraphqlSchemaFields }}{{- if eq $length 0 }}{{- else }} +type {{ $node.SchemaName }} @nexus(group:"{{ $node.GroupName}}",version:"{{ $node.ResourceVersion}}",kind:"{{ $node.Kind}}",resource:"{{ $node.ResourceName}}",name:"{{ $node.NodeName}}",crdName:"{{ $node.CrdName}}"){ + {{- range $key, $field := $node.GraphqlSchemaFields }} + {{- if $field.SchemaFieldName }} + {{ $field.SchemaFieldName -}} + {{- end}} + {{- end }} +} +{{- end }}{{- end }}{{- end }} + +{{- range $key, $val := .GraphQlFiles}} + {{ $val }} +{{- end }} diff --git a/compiler/pkg/generator/template/types.go.tmpl b/compiler/pkg/generator/template/types.go.tmpl index 1f8581297..539535664 100644 --- a/compiler/pkg/generator/template/types.go.tmpl +++ b/compiler/pkg/generator/template/types.go.tmpl @@ -22,10 +22,17 @@ type Link struct { Name string `json:"name" yaml:"name"` } +// +k8s:openapi-gen=true +type SyncerStatus struct { + EtcdVersion int64 `json:"etcdVersion, omitempty" yaml:"etcdVersion, omitempty"` + CRGenerationId int64 `json:"cRGenerationId, omitempty" yaml:"cRGenerationId, omitempty"` +} + // +k8s:openapi-gen=true type NexusStatus struct { - SourceGeneration int64 `json:"sourceGeneration" yaml:"sourceGeneration"` - RemoteGeneration int64 `json:"remoteGeneration" yaml:"remoteGeneration"` + SourceGeneration int64 `json:"sourceGeneration, omitempty" yaml:"sourceGeneration, omitempty"` + RemoteGeneration int64 `json:"remoteGeneration, omitempty" yaml:"remoteGeneration, omitempty"` + SyncerStatus SyncerStatus `json:"syncerStatus, omitempty" yaml:"syncerStatus, omitempty"` } /* ------------------- CRDs definitions ------------------- */ diff --git a/compiler/pkg/generator/template_renderers.go b/compiler/pkg/generator/template_renderers.go index 3ffdc471e..3530e49b0 100644 --- a/compiler/pkg/generator/template_renderers.go +++ b/compiler/pkg/generator/template_renderers.go @@ -6,6 +6,8 @@ import ( "encoding/json" "fmt" "go/format" + "go/printer" + "go/token" "os" "sort" "strings" @@ -55,9 +57,17 @@ var graphqlResolverTemplateFile []byte //go:embed template/graphql/server.go.tmpl var gqlserverTemplateFile []byte +//go:embed template/tsm-graphql/schema.graphqls.tmpl +var tsmGraphqlSchemaTemplateFile []byte + +//go:embed template/model.go.tmpl +var modelTemplateFile []byte + func RenderCRDTemplate(baseGroupName, crdModulePath string, - pkgs parser.Packages, graph map[string]parser.Node, outputDir string, - httpMethods map[string]nexus.HTTPMethodsResponses, httpCodes map[string]nexus.HTTPCodesResponse) error { + pkgs parser.Packages, graph map[string]parser.Node, + outputDir string, httpMethods map[string]nexus.HTTPMethodsResponses, + httpCodes map[string]nexus.HTTPCodesResponse, nonNexusTypes *parser.NonNexusTypes, + fileset *token.FileSet, graphqlFiles map[string]string) error { parentsMap := parser.CreateParentsMap(graph) pkgNames := make([]string, len(pkgs)) @@ -137,7 +147,7 @@ func RenderCRDTemplate(baseGroupName, crdModulePath string, return err } - err = RenderGraphQL(baseGroupName, outputDir, crdModulePath, pkgs, parentsMap) + err = RenderGraphQL(baseGroupName, outputDir, crdModulePath, pkgs, parentsMap, graphqlFiles, nonNexusTypes) if err != nil { return err } @@ -146,6 +156,11 @@ func RenderCRDTemplate(baseGroupName, crdModulePath string, if err != nil { return err } + + err = RenderNonNexusTypes(outputDir, nonNexusTypes, fileset) + if err != nil { + return err + } return nil } @@ -538,9 +553,10 @@ func RenderClientTemplate(baseGroupName, crdModulePath string, pkgs parser.Packa type GraphDetails struct { BaseImportPath string Nodes []NodeProperty + GraphQlFiles map[string]string } -func RenderGraphQL(baseGroupName, outputDir, crdModulePath string, pkgs parser.Packages, parentsMap map[string]parser.NodeHelper) error { +func RenderGraphQL(baseGroupName, outputDir, crdModulePath string, pkgs parser.Packages, parentsMap map[string]parser.NodeHelper, graphqlFiles map[string]string, nonNexusTypes *parser.NonNexusTypes) error { gqlFolder := outputDir + "/nexus-gql/graph" var ( vars GraphDetails @@ -549,6 +565,7 @@ func RenderGraphQL(baseGroupName, outputDir, crdModulePath string, pkgs parser.P vars.BaseImportPath = crdModulePath vars.Nodes, err = GenerateGraphqlResolverVars(baseGroupName, crdModulePath, pkgs, parentsMap) + vars.GraphQlFiles = graphqlFiles if err != nil { return err } @@ -586,6 +603,25 @@ func RenderGraphQL(baseGroupName, outputDir, crdModulePath string, pkgs parser.P return err } + //Render Graphql Schema Template (TSM) + vars.Nodes, err = GenerateTsmGraphqlSchemaVars(baseGroupName, crdModulePath, pkgs, parentsMap, nonNexusTypes) + if err != nil { + return err + } + tsmGqlFolder := outputDir + "/tsm-nexus-gql/graph" + schemaTemplate, err := readTemplateFile(tsmGraphqlSchemaTemplateFile) + if err != nil { + return err + } + tsmFile, err := renderTemplate(schemaTemplate, vars) + if err != nil { + return err + } + log.Debugf("Rendered graphql schema template: %s", tsmFile) + err = createFile(tsmGqlFolder, "schema.graphqls", tsmFile, false) + if err != nil { + return err + } return nil } @@ -649,3 +685,52 @@ func RenderGqlServerTemplate(vars ServerVars) (*bytes.Buffer, error) { } return renderTemplate(registerGqlserverTemplate, vars) } + +type CommonVars struct { + Types string +} + +func RenderNonNexusTypes(outputDir string, nonNexusTypes *parser.NonNexusTypes, fileset *token.FileSet) error { + outputModelFolder := outputDir + "/model" + err := createFolder(outputModelFolder) + if err != nil { + return err + } + + var output string + for _, decl := range nonNexusTypes.Types { + var buf bytes.Buffer + err := printer.Fprint(&buf, fileset, decl) + if err != nil { + return err + } + + output += fmt.Sprintf("%s\n\n", buf.String()) + } + + for _, val := range nonNexusTypes.Values { + output += fmt.Sprintf("%s\n\n", val) + } + + for _, val := range nonNexusTypes.ExternalTypes { + output += fmt.Sprintf("%s\n\n", val) + } + + vars := CommonVars{Types: output} + tmpl, err := readTemplateFile(modelTemplateFile) + if err != nil { + return err + } + + out, err := renderTemplate(tmpl, vars) + if err != nil { + return err + } + + err = createFile(outputModelFolder, "model.go", out, false) + if err != nil { + return err + } + + return nil +} diff --git a/compiler/pkg/generator/tsm_graphql_generator.go b/compiler/pkg/generator/tsm_graphql_generator.go new file mode 100644 index 000000000..2d2dc85e0 --- /dev/null +++ b/compiler/pkg/generator/tsm_graphql_generator.go @@ -0,0 +1,485 @@ +package generator + +import ( + "fmt" + "go/ast" + "regexp" + "sort" + "strings" + + log "github.com/sirupsen/logrus" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/parser" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/util" + "github.com/vmware-tanzu/graph-framework-for-microservices/nexus/nexus" +) + +type GraphQLSchemaType int + +const ( + Standard GraphQLSchemaType = iota + Array + JsonMarshal + Child + Link + NamedChild + NamedLink + AliasType +) + +// tsmPopulateValuesForEachNode populates each node with required resolver properties +func tsmPopulateValuesForEachNode(nodes []*NodeProperty, linkAPI map[string]string, retMap map[string]ReturnStatement) []NodeProperty { + var nodeProperties []NodeProperty + for _, n := range nodes { + resNodeProp := NodeProperty{} + resNodeProp.GroupResourceNameTitle = util.GetGroupResourceNameTitle(n.NodeName) + resNodeProp.Alias = n.Alias + resNodeProp.ReturnType = n.ReturnType + resNodeProp.BaseImportPath = n.BaseImportPath + resNodeProp.GraphqlSchemaFields = n.GraphqlSchemaFields + resNodeProp.IsSingletonNode = n.IsSingletonNode + resNodeProp.CustomQueries = n.CustomQueries + resNodeProp.IsNexusNode = n.IsNexusNode + resNodeProp.ResolverFields = n.ResolverFields + resNodeProp.ResolverCount = n.ResolverCount + resNodeProp.PkgName = n.PkgName + resNodeProp.NodeName = n.NodeName + resNodeProp.SchemaName = n.SchemaName + resNodeProp.GroupName = n.GroupName + resNodeProp.Singular = n.Singular + resNodeProp.Kind = n.Kind + resNodeProp.ResourceName = n.ResourceName + resNodeProp.ResourceVersion = n.ResourceVersion + resNodeProp.CrdName = n.CrdName + + // populate return values for root of the graph + if !n.HasParent && n.IsParentNode { + resNodeProp.Alias = retMap[resNodeProp.PkgName+resNodeProp.NodeName].Alias + resNodeProp.ReturnType = retMap[resNodeProp.PkgName+resNodeProp.NodeName].ReturnType + resNodeProp.IsParentNode = true + } + + // populate return values for child fields + for _, f := range n.ChildFields { + f.ReturnType = retMap[f.FieldTypePkgPath].ReturnType + f.Alias = retMap[f.FieldTypePkgPath].Alias + f.FieldCount = retMap[f.FieldTypePkgPath].FieldCount + f.CRDName = retMap[f.FieldTypePkgPath].CRDName + f.ChainAPI = retMap[f.FieldTypePkgPath].ChainAPI + f.IsSingleton = retMap[f.FieldTypePkgPath].IsSingleton + f.LinkAPI = linkAPI[f.PkgName+f.NodeName] + resNodeProp.ChildFields = append(resNodeProp.ChildFields, f) + } + + // populate return values for multiple child fields + for _, f := range n.ChildrenFields { + f.ReturnType = retMap[f.FieldTypePkgPath].ReturnType + f.Alias = retMap[f.FieldTypePkgPath].Alias + f.FieldCount = retMap[f.FieldTypePkgPath].FieldCount + f.CRDName = retMap[f.FieldTypePkgPath].CRDName + f.ChainAPI = retMap[f.FieldTypePkgPath].ChainAPI + f.IsSingleton = retMap[f.FieldTypePkgPath].IsSingleton + f.LinkAPI = linkAPI[f.PkgName+f.NodeName] + resNodeProp.ChildrenFields = append(resNodeProp.ChildrenFields, f) + } + + // populate return values for link fields + for _, f := range n.LinkFields { + f.ReturnType = retMap[f.FieldTypePkgPath].ReturnType + f.Alias = retMap[f.FieldTypePkgPath].Alias + f.FieldCount = retMap[f.FieldTypePkgPath].FieldCount + f.CRDName = retMap[f.FieldTypePkgPath].CRDName + f.ChainAPI = retMap[f.FieldTypePkgPath].ChainAPI + f.IsSingleton = retMap[f.FieldTypePkgPath].IsSingleton + f.LinkAPI = linkAPI[f.PkgName+f.NodeName] + resNodeProp.LinkFields = append(resNodeProp.LinkFields, f) + } + + // populate return values for multiple link fields + for _, f := range n.LinksFields { + f.ReturnType = retMap[f.FieldTypePkgPath].ReturnType + f.Alias = retMap[f.FieldTypePkgPath].Alias + f.FieldCount = retMap[f.FieldTypePkgPath].FieldCount + f.CRDName = retMap[f.FieldTypePkgPath].CRDName + f.ChainAPI = retMap[f.FieldTypePkgPath].ChainAPI + f.IsSingleton = retMap[f.FieldTypePkgPath].IsSingleton + f.LinkAPI = linkAPI[f.PkgName+f.NodeName] + resNodeProp.LinksFields = append(resNodeProp.LinksFields, f) + } + + nodeProperties = append(nodeProperties, resNodeProp) + } + + return nodeProperties +} + +func tsmPopulateValuesForResolver(nodes []*NodeProperty, parentsMap map[string]parser.NodeHelper, + crdNameMap, nonStructMap map[string]string) (map[string]string, map[string]ReturnStatement) { + linkAPI := make(map[string]string) + retMap := make(map[string]ReturnStatement) + + for _, n := range nodes { + var ( + retType, aliasVal, listRetVal, ChainAPI string + fieldCount int + IsSingleton bool + ) + + retType += fmt.Sprintf("ret := &model.%s%s {\n", n.PkgName, n.NodeName) + if n.IsNexusNode || n.IsSingletonNode { + retType += fmt.Sprintf("\t%s: &%s,\n", "Id", "dn") + aliasVal += fmt.Sprintf("%s := v%s.DisplayName()\n", "dn", n.NodeName) + + retType += fmt.Sprintf("\t%s: %s,\n", "ParentLabels", "parentLabels") + aliasVal += fmt.Sprintf("%s := map[string]interface{}{%q:%s}\n", "parentLabels", n.CrdName, "dn") + + ChainAPI += "nc" + var prevNode parser.NodeHelper + for _, i := range parentsMap[n.CrdName].Parents { + currentNode := parentsMap[i] + + if len(currentNode.Parents) == 0 { + // root of the graph + if currentNode.IsSingleton { + ChainAPI += fmt.Sprintf(".%s()", crdNameMap[i]) + } else { + ChainAPI += fmt.Sprintf(".%s(getParentName(obj.ParentLabels, %q))", crdNameMap[i], i) + } + } else { + if childNode, ok := prevNode.Children[i]; ok { + if currentNode.IsSingleton { + ChainAPI += fmt.Sprintf(".%s()", childNode.FieldName) + } else { + ChainAPI += fmt.Sprintf(".%s(getParentName(obj.ParentLabels, %q))", childNode.FieldName, i) + } + } + } + // cache the non-leaf node + prevNode = currentNode + } + + // Create linkAPI + if n.IsSingletonNode { + IsSingleton = true + if !n.HasParent && n.IsParentNode { + linkAPI[n.PkgName+n.NodeName] = fmt.Sprintf("%s.Get%s(context.TODO())", ChainAPI, n.PkgName+n.NodeName) + } else { + linkAPI[n.PkgName+n.NodeName] = fmt.Sprintf("%s.Get%s(context.TODO())", ChainAPI, prevNode.Children[n.CrdName].FieldName) + } + } else { + IsSingleton = false + if !n.HasParent && n.IsParentNode { + linkAPI[n.PkgName+n.NodeName] = fmt.Sprintf("%s.Get%s(context.TODO(), getParentName(obj.ParentLabels, %q))", ChainAPI, n.PkgName+n.NodeName, n.CrdName) + } else { + linkAPI[n.PkgName+n.NodeName] = fmt.Sprintf("%s.Get%s(context.TODO(), getParentName(obj.ParentLabels, %q))", ChainAPI, prevNode.Children[n.CrdName].FieldName, n.CrdName) + } + } + } + for _, i := range n.ResolverFields[n.PkgName+n.NodeName] { + if i.IsMapTypeField || i.IsStringType { + fieldCount += 1 + retType += fmt.Sprintf("\t%s: &%sData,\n", i.FieldName, i.FieldName) + aliasVal += jsonMarshalResolver(i.FieldName, n.NodeName) + } else if i.IsStdTypeField { + if len(convertGoStdType(i.FieldType)) != 0 { + fieldCount += 1 + retType += fmt.Sprintf("\t%s: &v%s,\n", i.FieldName, i.FieldName) + listRetVal += fmt.Sprintf("v%s := %s(i.%s)\n", i.FieldName, convertGoStdType(i.FieldType), i.FieldName) + aliasVal += fmt.Sprintf("v%s := %s(v%s.Spec.%s)\n", i.FieldName, convertGoStdType(i.FieldType), i.NodeName, i.FieldName) + } + } + } + retType += "\t}" + retMap[n.PkgName+n.NodeName] = ReturnStatement{ + Alias: aliasVal, + ReturnType: retType, + FieldCount: fieldCount, + CRDName: n.CrdName, + ChainAPI: ChainAPI, + IsSingleton: IsSingleton, + } + } + + return linkAPI, retMap +} + +// tsmProcessNonNexusFields process and populates properties for each non nexus fields +// +func tsmProcessNonNexusFields(pkg parser.Package, aliasNameMap map[string]string, node *ast.TypeSpec, nodeProp *NodeProperty, simpleGroupTypeName string, nonNexusTypes *parser.NonNexusTypes) { + resField := make(map[string][]FieldProperty) + for _, f := range parser.GetSpecFields(node) { + var ( + fieldProp FieldProperty + err error + ) + typeString := ConstructType(aliasNameMap, f) + // populate each field properties + if len(f.Names) > 0 { + fieldProp.FieldName, err = parser.GetNodeFieldName(f) + if err != nil { + log.Fatalf("failed to determine field name: %v", err) + } + fieldProp.FieldType = typeString + fieldProp.PkgName = simpleGroupTypeName + fieldProp.NodeName = node.Name.String() + } + + if parser.IgnoreField(f) { + continue + } + + if parser.IsJsonStringField(f) { + fieldProp.IsStringType = true + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(JsonMarshal, fieldProp.FieldName, "String", "id: ID", f, pkg, nonNexusTypes) + resField[nodeProp.PkgName+nodeProp.NodeName] = append(resField[nodeProp.PkgName+nodeProp.NodeName], fieldProp) + } else if parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_ALIAS_TYPE_ANNOTATION) || parser.IsFieldAnnotationPresent(f, parser.GRAPHQL_ALIAS_NAME_ANNOTATION) { + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(AliasType, fieldProp.FieldName, "", "", f, pkg, nonNexusTypes) + resField[nodeProp.PkgName+nodeProp.NodeName] = append(resField[nodeProp.PkgName+nodeProp.NodeName], fieldProp) + } else if parser.IsArrayField(f) { + arr := regexp.MustCompile(`^(\[])`).ReplaceAllString(typeString, "") + if !strings.Contains(arr, ".") { + stdType := convertGraphqlStdType(arr) + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(Array, fieldProp.FieldName, stdType, "id: ID", f, pkg, nonNexusTypes) + resField[nodeProp.PkgName+nodeProp.NodeName] = append(resField[nodeProp.PkgName+nodeProp.NodeName], fieldProp) + } + } else { + stdType := convertGraphqlStdType(typeString) + // standard type + if len(stdType) != 0 { + fieldProp.IsStdTypeField = true + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(Standard, fieldProp.FieldName, stdType, "id: ID", f, pkg, nonNexusTypes) + resField[nodeProp.PkgName+nodeProp.NodeName] = append(resField[nodeProp.PkgName+nodeProp.NodeName], fieldProp) + } else { + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(Standard, fieldProp.FieldName, "String", "id: ID", f, pkg, nonNexusTypes) + fieldProp.IsStringType = true + resField[nodeProp.PkgName+nodeProp.NodeName] = append(resField[nodeProp.PkgName+nodeProp.NodeName], fieldProp) + } + } + nodeProp.GraphqlSchemaFields = append(nodeProp.GraphqlSchemaFields, fieldProp) + nodeProp.ResolverFields = resField + } +} + +// tsmProcessNexusFields process and populates properties for each nexus fields +// +func tsmProcessNexusFields(pkg parser.Package, aliasNameMap map[string]string, node *ast.TypeSpec, + nodeProp *NodeProperty, simpleGroupTypeName string, pkgs map[string]parser.Package, + gqlSpecMap map[string]nexus.GraphQLSpec) { + importMap := pkg.GetImportMap() + for _, nf := range parser.GetNexusFields(node) { + var ( + fieldProp FieldProperty + err error + ) + if len(nf.Names) > 0 { + fieldProp.FieldName, err = parser.GetNodeFieldName(nf) + if err != nil { + log.Fatalf("Failed to determine field name: %v", err) + } + fieldProp.PkgName = simpleGroupTypeName + fieldProp.NodeName = node.Name.String() + } + + // Except for nexus fields (nexus.Node and nexus.SingletonNode), + // this will check other fields to see whether they have nexus secrets annotated on them + // If yes, the field is ignored in the response. + if !parser.IsNexusTypeField(nf) { + nfType := parser.GetFieldType(nf) + fieldPkg := &pkg + structType := nfType + + if ptParts := strings.Split(nfType, "."); len(ptParts) == 2 { //service_group.SvcGroup + structType, fieldPkg = findTypeAndPkgForField(ptParts, importMap, pkgs) + } + if len(structType) != 0 { + if _, ok := parser.GetNexusSecretSpecAnnotation(*fieldPkg, structType); ok { + log.Debugf("Ignoring the field %s since the node is annotated as nexus secret", fieldProp.FieldName) + continue + } + } + } + + // `Ignore:true` annotation used to ignore the specific field `nexus-graphql:"ignore:true"` + if parser.IgnoreField(nf) { + continue + } + // `type:string` annotation used to consider the type as string `nexus-graphql:"type:string"` + if parser.IsJsonStringField(nf) { + fieldProp.IsStringType = true + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(JsonMarshal, fieldProp.FieldName, "String", "id: ID", nf, pkg, nil) + } + + // denote field is nexus or singletonField type + if parser.IsNexusTypeField(nf) { + fieldProp.IsNexusOrSingletonField = true + // get nexus schemaFieldName from GraphQlSpec "IdName" & "IdNullable" + fieldProp.SchemaFieldName = GetNexusSchemaFieldName(nodeProp.GraphQlSpec) + for _, customQuery := range nodeProp.CustomQueries { + cq := CustomQueryToGraphqlSchema(customQuery) + // In TSM DM "@timeseriesAPI" directives is need to added along with returnType "TimeSeriesData" + fieldProp.SchemaFieldName += "\n" + strings.ReplaceAll(cq, "TimeSeriesData", fmt.Sprintf("TimeSeriesData @timeseriesAPI(file: \"../../tsquery/timeSeriesQuery\", handler: \"%s\")", customQuery.Name)) + var customQueryFieldProp FieldProperty + customQueryFieldProp.IsResolver = true + customQueryFieldProp.FieldName = customQuery.Name + nodeProp.GraphqlSchemaFields = append(nodeProp.GraphqlSchemaFields, customQueryFieldProp) + nodeProp.ResolverCount += 1 + } + } + + // nexus link field + typeString := ConstructType(aliasNameMap, nf) + if parser.IsOnlyLinkField(nf) { + schemaTypeName, resolverTypeName := ValidateImportPkg(nodeProp.PkgName, typeString, importMap, pkgs) + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(Link, fieldProp.FieldName, schemaTypeName, "id: ID", nf, pkg, nil) + fieldProp.IsResolver = true + fieldProp.IsNexusTypeField = true + fieldProp.FieldType = typeString + fieldProp.FieldTypePkgPath = resolverTypeName + fieldProp.SchemaTypeName = schemaTypeName + fieldProp.BaseTypeName = getBaseNodeType(typeString) + nodeProp.LinkFields = append(nodeProp.LinkFields, fieldProp) + } + + // nexus child field + if parser.IsOnlyChildField(nf) { + schemaTypeName, resolverTypeName := ValidateImportPkg(nodeProp.PkgName, typeString, importMap, pkgs) + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(Child, fieldProp.FieldName, schemaTypeName, "id: ID", nf, pkg, nil) + fieldProp.SchemaTypeName = schemaTypeName + fieldProp.IsResolver = true + fieldProp.IsNexusTypeField = true + fieldProp.FieldType = typeString + fieldProp.FieldTypePkgPath = resolverTypeName + fieldProp.BaseTypeName = getBaseNodeType(typeString) + nodeProp.ChildFields = append(nodeProp.ChildFields, fieldProp) + } + + // nexus children or links field + if parser.IsNamedChildOrLink(nf) { + var listArg string + fieldProp.IsChildrenOrLinks = true + schemaTypeName, resolverTypeName := ValidateImportPkg(nodeProp.PkgName, typeString, importMap, pkgs) + // Annotation `nexus-graphql-args:"name: String"` use to specify graphql arguments + AnnotatedGqlArgs := parser.GetFieldAnnotationVal(nf, parser.GRAPHQL_ARGS_ANNOTATION) + if AnnotatedGqlArgs != "" { + listArg = AnnotatedGqlArgs + } else { + if val, ok := parser.GetNexusGraphqlSpecAnnotation(pkg, typeString); ok { + gqlspec := gqlSpecMap[fmt.Sprintf("%s.%s", pkg.Name, val)] + listArg = GetNexusSchemaFieldName(gqlspec) + } else { + listArg = GetNodeDetails(nodeProp.PkgName, typeString, importMap, pkgs, gqlSpecMap) + } + } + + sType := NamedChild + if parser.IsLinkField(nf) { + sType = NamedLink + } + fieldProp.SchemaFieldName = getTsmGraphqlSchemaFieldName(sType, fieldProp.FieldName, schemaTypeName, listArg, nf, pkg, nil) + fieldProp.IsResolver = true + fieldProp.IsNexusTypeField = true + fieldProp.FieldType = typeString + fieldProp.FieldTypePkgPath = resolverTypeName + fieldProp.BaseTypeName = getBaseNodeType(typeString) + if parser.IsOnlyChildrenField(nf) { + nodeProp.ChildrenFields = append(nodeProp.ChildrenFields, fieldProp) + } else { + nodeProp.LinksFields = append(nodeProp.LinksFields, fieldProp) + } + } + // no. of resolver field in a node + if fieldProp.IsResolver { + nodeProp.ResolverCount += 1 + } + nodeProp.GraphqlSchemaFields = append(nodeProp.GraphqlSchemaFields, fieldProp) + } +} + +// GenerateTsmGraphqlSchemaVars populates the node and its field properties required to generate graphql resolver +func GenerateTsmGraphqlSchemaVars(baseGroupName, crdModulePath string, pkgs parser.Packages, parentsMap map[string]parser.NodeHelper, nonNexusTypes *parser.NonNexusTypes) ([]NodeProperty, error) { + sortedKeys := make([]string, 0, len(pkgs)) + gqlSpecMap := parser.ParseGraphqlSpecs(pkgs) + for k := range pkgs { + sortedKeys = append(sortedKeys, k) + } + sort.Strings(sortedKeys) + sortedPackages := make([]parser.Package, len(pkgs)) + for i, k := range sortedKeys { + sortedPackages[i] = pkgs[k] + } + + // Iterate all the struct type and it's fields in the sortedPackages and + // set the node and field properties accordingly. + var nodes []*NodeProperty + aliasNameMap := make(map[string]string) + //rootOfGraph := false + for _, pkg := range sortedPackages { + simpleGroupTypeName := util.GetSimpleGroupTypeName(pkg.Name) + // Iterating struct type + for _, node := range pkg.GetStructs() { + // Nexus GraphQlSpec by default "IdNullable" value is true + gqlspec := nexus.GraphQLSpec{ + IdName: "", + IdNullable: true, + } + // Skip Empty struct type + if len(parser.GetNexusFields(node)) == 0 && len(parser.GetSpecFields(node)) == 0 { + continue + } + + typeName := parser.GetTypeName(node) + if _, ok := parser.GetNexusSecretSpecAnnotation(pkg, typeName); ok { + log.Debugf("Ignoring the node %s since the node is annotated as nexus secret", typeName) + continue + } + + if val, ok := parser.GetNexusGraphqlSpecAnnotation(pkg, typeName); ok { + gqlspec = gqlSpecMap[fmt.Sprintf("%s.%s", pkg.Name, val)] + } + + nodeProp := &NodeProperty{} + // populate node properties + nodeProp.PkgName = simpleGroupTypeName + nodeProp.NodeName = node.Name.String() + nodeProp.BaseImportPath = crdModulePath + nodeProp.CrdName = util.GetCrdName(node.Name.String(), pkg.Name, baseGroupName) + nodeHelper := parentsMap[nodeProp.CrdName] + nodeProp.IsParentNode = parser.IsNexusNode(node) + nodeProp.CustomQueries = nodeHelper.GraphqlQuerySpec.Queries + nodeProp.GraphQlSpec = gqlspec + nodeProp.GroupName = pkg.Name + "." + baseGroupName + nodeProp.Singular = strings.ToLower(typeName) + nodeProp.Kind = cases.Title(language.Und, cases.NoLower).String(typeName) + nodeProp.ResourceName = util.ToPlural(nodeProp.Singular) + nodeProp.ResourceVersion = "v1" + // crdName := fmt.Sprintf("%s.%s", plural, groupName) + + setNexusProperties(nodeHelper, node, nodeProp) + if pkg.Name == "global" { + nodeProp.SchemaName = parser.GetTypeName(node) + } else if pkg.Name == "tsm" { + continue + } else { + nodeProp.SchemaName = fmt.Sprintf("%s_%s", pkg.Name, parser.GetTypeName(node)) + } + // Iterate each node's nexus fields and set its properties + tsmProcessNexusFields(pkg, aliasNameMap, node, nodeProp, simpleGroupTypeName, pkgs, gqlSpecMap) + + // Iterate each node's non-nexus fields and set its properties + tsmProcessNonNexusFields(pkg, aliasNameMap, node, nodeProp, simpleGroupTypeName, nonNexusTypes) + nodes = append(nodes, nodeProp) + } + } + + crdNameMap := constructNexusTypeMap(nodes) + // populate return values of each Node for resolver + nonStructMap := constructAliasType(sortedPackages) + linkAPI, retMap := tsmPopulateValuesForResolver(nodes, parentsMap, crdNameMap, nonStructMap) + + // populate return values of each node + nodeProperties := tsmPopulateValuesForEachNode(nodes, linkAPI, retMap) + + return nodeProperties, nil +} diff --git a/compiler/pkg/generator/tsm_graphql_generator_test.go b/compiler/pkg/generator/tsm_graphql_generator_test.go new file mode 100644 index 000000000..72874106a --- /dev/null +++ b/compiler/pkg/generator/tsm_graphql_generator_test.go @@ -0,0 +1,79 @@ +package generator_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/vmware-tanzu/graph-framework-for-microservices/nexus/nexus" + + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/generator" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/parser" +) + +var _ = Describe("Template renderers tests", func() { + var ( + pkgs parser.Packages + parentsMap map[string]parser.NodeHelper + graphqlQueries map[string]nexus.GraphQLQuerySpec + ) + + BeforeEach(func() { + pkgs = parser.ParseDSLPkg(exampleDSLPath) + graphqlQueries = parser.ParseGraphqlQuerySpecs(pkgs) + graph, _, _ := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + parentsMap = parser.CreateParentsMap(graph) + }) + + FIt("should resolve graphql vars", func() { + vars, err := generator.GenerateTsmGraphqlSchemaVars(baseGroupName, crdModulePath, pkgs, parentsMap, nil) + Expect(err).NotTo(HaveOccurred()) + + Expect(len(vars)).To(Equal(45)) + Expect(vars[0].NodeName).To(Equal("Root")) + Expect(vars[3].PkgName).To(Equal("Config")) + Expect(vars[3].NodeName).To(Equal("Config")) + Expect(vars[3].SchemaName).To(Equal("config_Config")) + Expect(vars[3].Alias).To(Equal("")) + Expect(vars[3].ReturnType).To(Equal("")) + + Expect(vars[2].IsParentNode).To(BeFalse()) + Expect(vars[2].HasParent).To(BeFalse()) + Expect(vars[2].IsSingletonNode).To(BeFalse()) + Expect(vars[2].IsNexusNode).To(BeFalse()) + Expect(vars[2].BaseImportPath).To(Equal("nexustempmodule/")) + Expect(vars[2].CrdName).To(Equal("")) + + // Test that nexus-secret Node should not be present + Expect(vars).NotTo(ContainElement(HaveField("NodeName", "Foo"))) + }) + + It("should resolve non-singleton root and singleton child node", func() { + pkgs = parser.ParseDSLPkg("../../example/test-utils/non-singleton-root") + graph, _, _ := parser.ParseDSLNodes("../../example/test-utils/non-singleton-root", baseGroupName, pkgs, graphqlQueries) + parentsMap = parser.CreateParentsMap(graph) + + vars, err := generator.GenerateGraphqlResolverVars(baseGroupName, crdModulePath, pkgs, parentsMap) + Expect(err).NotTo(HaveOccurred()) + Expect(len(vars)).To(Equal(3)) + + Expect(vars[0].NodeName).To(Equal("Root")) + Expect(vars[1].PkgName).To(Equal("Config")) + Expect(vars[1].NodeName).To(Equal("Config")) + Expect(vars[1].SchemaName).To(Equal("config_Config")) + + Expect(vars[1].IsParentNode).To(BeFalse()) + Expect(vars[1].HasParent).To(BeFalse()) + Expect(vars[1].IsSingletonNode).To(BeTrue()) + Expect(vars[1].IsNexusNode).To(BeTrue()) + Expect(vars[1].BaseImportPath).To(Equal("nexustempmodule/")) + Expect(vars[1].CrdName).To(Equal("")) + }) + + It("should validate the import pkg and translate to graphql schema and resolver typeName", func() { + pkg := pkgs["github.com/vmware-tanzu/graph-framework-for-microservices/compiler/example/datamodel/config/gns"] + schemaTypeName, resolverTypeName := generator.ValidateImportPkg(pkg.Name, "servicegroup.SvcGroup", pkg.GetImportMap(), pkgs) + + Expect(pkg.Name).To(Equal("gns")) + Expect(schemaTypeName).To(Equal("servicegroup_SvcGroup")) + Expect(resolverTypeName).To(Equal("ServicegroupSvcGroup")) + }) +}) diff --git a/compiler/pkg/generator/types_generator.go b/compiler/pkg/generator/types_generator.go index 6f1158745..16bd3348c 100644 --- a/compiler/pkg/generator/types_generator.go +++ b/compiler/pkg/generator/types_generator.go @@ -150,6 +150,7 @@ type {{.Name}}Spec struct { Name string Fields string } + specDef.Name = parser.GetTypeName(node) for _, field := range parser.GetSpecFields(node) { @@ -170,8 +171,14 @@ type {{.Name}}Spec struct { } specDef.Fields += "\t" + name + " " typeString := ConstructType(aliasNameMap, field) - specDef.Fields += typeString + // Type is set to "any" for field with annotation "nexus-graphql-jsonencoded" + if parser.IsFieldAnnotationPresent(field, parser.GRAPHQL_JSONENCODED_ANNOTATION) { + specDef.Fields += "nexus.NexusGenericObject" + } else { + specDef.Fields += typeString + } specDef.Fields += " " + getTag(field, name, false) + "\n" + } for _, child := range parser.GetChildFields(node) { diff --git a/compiler/pkg/openapi_generator/default_schemas.go b/compiler/pkg/openapi_generator/default_schemas.go index 945723965..71973d514 100644 --- a/compiler/pkg/openapi_generator/default_schemas.go +++ b/compiler/pkg/openapi_generator/default_schemas.go @@ -313,10 +313,17 @@ func defaultSchemas() map[string]common.OpenAPIDefinition { k8sAPIMachineryTypeName("apis/meta/v1.ListMeta"): schemaForTypeAndFormat("object", noFormat), k8sAPIMachineryTypeName("apis/meta/v1.ObjectMeta"): schemaForTypeAndFormat("object", noFormat), k8sAPIMachineryTypeName("apis/meta/v1.Time"): schemaForTypeAndFormat("string", noFormat), + k8sAPIMachineryTypeName("util/intstr.IntOrString"): schemaForOneOf( + schemaForTypeAndFormat("integer", noFormat), + schemaForTypeAndFormat("string", noFormat), + ), envoyTypeName("config/core/v3.grpcservice"): schemaForTypeAndFormat("object", noFormat), envoyTypeName("extensions/access_loggers/grpc/v3.commongrpcaccesslogconfig"): schemaForTypeAndFormat("object", noFormat), + // any is an alias for interface{} + // "nexusType": schemaForAnyTypeAndFormat("any", noFormat), + nexusTypeName("nexus.NexusGenericObject"): schemaForAnyTypeAndFormat("any", noFormat), // The `openapi-gen` cannot generate Go schema for struct builtin. We mark is // as an object which allows any properties inside "struct{}": schemaForTypeAndFormat("object", noFormat), @@ -325,6 +332,7 @@ func defaultSchemas() map[string]common.OpenAPIDefinition { // defaultSchema is used when YAML generator can't find a schema for given key. // It will also add the missing schema to `missingDefinitions` which can be accessed // with `MissingDefinitions()`. + // defaultSchema: schemaForNonTypeAndFormat("empty", noFormat), defaultSchema: schemaForTypeAndFormat("object", noFormat), } } @@ -349,6 +357,10 @@ func envoyTypeName(name string) string { return fmt.Sprintf("github.com/envoyproxy/go-control-plane/envoy/%v", name) } +func nexusTypeName(name string) string { + return fmt.Sprintf("github.com/vmware-tanzu/graph-framework-for-microservices/nexus/%v", name) +} + func schemaForOneOf(schemas ...common.OpenAPIDefinition) common.OpenAPIDefinition { s := common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -379,3 +391,17 @@ func schemaForTypeAndFormat(schemaType, schemaFormat string) common.OpenAPIDefin } return s } + +func schemaForAnyTypeAndFormat(schemaTitle, schemaFormat string) common.OpenAPIDefinition { + s := common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Title: schemaTitle, + }, + }, + } + if schemaFormat != noFormat { + s.Schema.SchemaProps.Format = schemaFormat + } + return s +} diff --git a/compiler/pkg/openapi_generator/generator.go b/compiler/pkg/openapi_generator/generator.go index 96ce548c8..4f5470b09 100644 --- a/compiler/pkg/openapi_generator/generator.go +++ b/compiler/pkg/openapi_generator/generator.go @@ -183,18 +183,6 @@ func (g *Generator) resolveRefsForPackage(pkg string) error { } fmt.Printf("Resolving refs for %v\n", pkg) - // We are forcing camelCase in all field names for consistency - for property, propSchema := range pkgSchema.schema.Properties { - if strings.Contains(property, "_") { - pkgSchema.schema.Properties[convertToCamelCase(property)] = propSchema - delete(pkgSchema.schema.Properties, property) - } - toReplace := make([]string, len(pkgSchema.schema.Required)) - for i, required := range pkgSchema.schema.Required { - toReplace[i] = convertToCamelCase(required) - } - pkgSchema.schema.Required = toReplace - } g.resolveRefsInProperty(pkgSchema.schema) g.resolveRefsInProperties(pkgSchema.schema) @@ -227,6 +215,14 @@ func (g *Generator) addKubernetesExtensionsFlags(schema *extensionsv1.JSONSchema t := true schema.XPreserveUnknownFields = &t } + // any is an alias for struct{} + // - x-kubernetes-preserve-unknown-fields: true + if schema.Title == "any" { + t := true + schema.XPreserveUnknownFields = &t + schema.Title = "" // reset Title + } + if len(schema.AnyOf) > 0 { schema.XIntOrString = true } diff --git a/compiler/pkg/parser/graphql_file_parser.go b/compiler/pkg/parser/graphql_file_parser.go new file mode 100644 index 000000000..0659ba973 --- /dev/null +++ b/compiler/pkg/parser/graphql_file_parser.go @@ -0,0 +1,39 @@ +package parser + +import ( + log "github.com/sirupsen/logrus" + "io/fs" + "os" + "path/filepath" +) + +// ParseDSLNodes walks recursively through given path and looks for structs types definitions to add them to graph +func ParseGraphQLFiles(startPath string) map[string]string { + graphqlFiles := make(map[string]string, 0) + err := filepath.Walk(startPath, func(path string, info fs.FileInfo, err error) error { + if info.IsDir() { + if info.Name() == "build" { + log.Infof("Ignoring build directory...") + return filepath.SkipDir + } + if info.Name() == "vendor" { + log.Infof("Ignoring vendor directory...") + return filepath.SkipDir + } + } else { + if filepath.Ext(path) == ".graphql" { + data, err := os.ReadFile(path) + if err != nil { + return err + } + graphqlFiles[path] = string(data) + } + } + return nil + }) + if err != nil { + log.Fatalf("Failed to ParseDSLNodes %v", err) + } + + return graphqlFiles +} diff --git a/compiler/pkg/parser/graphql_queries_parser.go b/compiler/pkg/parser/graphql_queries_parser.go index 8f7633696..a43c3af49 100644 --- a/compiler/pkg/parser/graphql_queries_parser.go +++ b/compiler/pkg/parser/graphql_queries_parser.go @@ -117,8 +117,9 @@ func parseQuery(queryComp *ast.CompositeLit, p Package) (newQuery nexus.GraphQLQ } type GraphQlArg struct { - Name string - Type string + Name string + Type string + AliasType bool } func parseArgs(argsTypeName string, p Package) []GraphQlArg { @@ -133,9 +134,25 @@ func parseArgs(argsTypeName string, p Package) []GraphQlArg { if len(field.Names) == 0 { log.Fatalf("Field in graphql args must be named, args %s", argsTypeName) } + // AliasName Annotation + var fName, fType string + var aType bool + if val := GetFieldAnnotationVal(field, GRAPHQL_ALIAS_NAME_ANNOTATION); val != "" { + fName = val + } else { + fName = field.Names[0].Name + } + // AliasType Annotation + if val := GetFieldAnnotationVal(field, GRAPHQL_ALIAS_TYPE_ANNOTATION); val != "" { + fType = val + aType = true + } else { + fType = GetFieldType(field) + } args = append(args, GraphQlArg{ - Name: field.Names[0].Name, - Type: GetFieldType(field), + Name: fName, + Type: fType, + AliasType: aType, }) } } diff --git a/compiler/pkg/parser/graphql_spec_parser.go b/compiler/pkg/parser/graphql_spec_parser.go new file mode 100644 index 000000000..b20024376 --- /dev/null +++ b/compiler/pkg/parser/graphql_spec_parser.go @@ -0,0 +1,56 @@ +package parser + +import ( + "go/ast" + "strconv" + + log "github.com/sirupsen/logrus" + "github.com/vmware-tanzu/graph-framework-for-microservices/nexus/nexus" +) + +func ParseGraphqlSpecs(pkgs Packages) map[string]nexus.GraphQLSpec { + graphQLSpecMap := make(map[string]nexus.GraphQLSpec) + for _, pkg := range pkgs { + GetGraphqlSpecs(graphQLSpecMap, pkg) + } + return graphQLSpecMap +} + +func GetGraphqlSpecs(graphQLSpecMap map[string]nexus.GraphQLSpec, p Package) { + for _, spec := range GetNexusSpecs(p, "nexus.GraphQLSpec") { + graphQLSpecMap[p.Name+"."+spec.Name] = parseGqlSpec(spec.Value, p) + } +} + +func parseGqlSpec(v *ast.CompositeLit, p Package) nexus.GraphQLSpec { + spec := nexus.GraphQLSpec{ + IdName: "", + IdNullable: true, + } + for _, gqlSpecElt := range v.Elts { + gqlSpecKv, ok := gqlSpecElt.(*ast.KeyValueExpr) + if !ok { + log.Fatalf("Wrong format of graphql query spec, please check graphql spec") + } + + gqlSpecFieldName := gqlSpecKv.Key.(*ast.Ident) + switch gqlSpecFieldName.String() { + case "IdName": + gqlSpecFieldValue := gqlSpecKv.Value.(*ast.BasicLit) + name, err := strconv.Unquote(gqlSpecFieldValue.Value) + if err != nil { + log.Fatalf("Internal compiler error, failed to unqote name in graphql") + } + spec.IdName = name + case "IdNullable": + gqlSpecFieldValue := gqlSpecKv.Value.(*ast.Ident) + val := gqlSpecFieldValue.String() + if val == "false" { + spec.IdNullable = false + } else { + spec.IdNullable = true + } + } + } + return spec +} diff --git a/compiler/pkg/parser/graphql_test.go b/compiler/pkg/parser/graphql_test.go index 2bc3ceb5d..244898ef1 100644 --- a/compiler/pkg/parser/graphql_test.go +++ b/compiler/pkg/parser/graphql_test.go @@ -17,7 +17,7 @@ var _ = Describe("Graphql parsing tests", func() { It("should parse graphql query specs", func() { pkgs = parser.ParseDSLPkg(exampleDSLPath) graphqlQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + graph, _, _ = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) root, ok := graph["roots.root.tsm.tanzu.vmware.com"] Expect(ok).To(BeTrue()) config, ok := root.SingleChildren["Config"] @@ -25,11 +25,11 @@ var _ = Describe("Graphql parsing tests", func() { gns, ok := config.SingleChildren["GNS"] Expect(ok).To(BeTrue()) - Expect(gns.GraphqlSpec.Queries).To(HaveLen(3)) - Expect(gns.GraphqlSpec.Queries[0].Name).To(Equal("queryGns1")) - Expect(gns.GraphqlSpec.Queries[0].ServiceEndpoint.Domain).To(Equal("nexus-query-responder")) - Expect(gns.GraphqlSpec.Queries[0].ServiceEndpoint.Port).To(Equal(15000)) - args := gns.GraphqlSpec.Queries[0].Args.([]parser.GraphQlArg) + Expect(gns.GraphqlQuerySpec.Queries).To(HaveLen(3)) + Expect(gns.GraphqlQuerySpec.Queries[0].Name).To(Equal("queryGns1")) + Expect(gns.GraphqlQuerySpec.Queries[0].ServiceEndpoint.Domain).To(Equal("nexus-query-responder")) + Expect(gns.GraphqlQuerySpec.Queries[0].ServiceEndpoint.Port).To(Equal(15000)) + args := gns.GraphqlQuerySpec.Queries[0].Args.([]parser.GraphQlArg) Expect(len(args)).To(Equal(5)) Expect(args[0].Name).To(Equal("StartTime")) @@ -43,26 +43,26 @@ var _ = Describe("Graphql parsing tests", func() { Expect(args[4].Name).To(Equal("StartVal")) Expect(args[4].Type).To(Equal("int")) - Expect(gns.GraphqlSpec.Queries[1].Name).To(Equal("queryGnsQM1")) - Expect(gns.GraphqlSpec.Queries[1].ServiceEndpoint.Domain).To(Equal("query-manager")) - Expect(gns.GraphqlSpec.Queries[1].ServiceEndpoint.Port).To(Equal(15002)) - Expect(gns.GraphqlSpec.Queries[1].Args).To(BeNil()) + Expect(gns.GraphqlQuerySpec.Queries[1].Name).To(Equal("queryGnsQM1")) + Expect(gns.GraphqlQuerySpec.Queries[1].ServiceEndpoint.Domain).To(Equal("query-manager")) + Expect(gns.GraphqlQuerySpec.Queries[1].ServiceEndpoint.Port).To(Equal(15002)) + Expect(gns.GraphqlQuerySpec.Queries[1].Args).To(BeNil()) }) It("should match graphql query specs from other packages", func() { pkgs = parser.ParseDSLPkg(exampleDSLPath) graphqlQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + graph, _, _ = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) root, ok := graph["roots.root.tsm.tanzu.vmware.com"] Expect(ok).To(BeTrue()) config, ok := root.SingleChildren["Config"] Expect(ok).To(BeTrue()) - Expect(config.GraphqlSpec.Queries).To(HaveLen(1)) - Expect(config.GraphqlSpec.Queries[0].Name).To(Equal("QueryExample")) - Expect(config.GraphqlSpec.Queries[0].ServiceEndpoint.Domain).To(Equal("query-manager")) - Expect(config.GraphqlSpec.Queries[0].ServiceEndpoint.Port).To(Equal(6000)) - args := config.GraphqlSpec.Queries[0].Args.([]parser.GraphQlArg) + Expect(config.GraphqlQuerySpec.Queries).To(HaveLen(1)) + Expect(config.GraphqlQuerySpec.Queries[0].Name).To(Equal("QueryExample")) + Expect(config.GraphqlQuerySpec.Queries[0].ServiceEndpoint.Domain).To(Equal("query-manager")) + Expect(config.GraphqlQuerySpec.Queries[0].ServiceEndpoint.Port).To(Equal(6000)) + args := config.GraphqlQuerySpec.Queries[0].Args.([]parser.GraphQlArg) Expect(len(args)).To(Equal(5)) }) diff --git a/compiler/pkg/parser/node.go b/compiler/pkg/parser/node.go index 7c5a7ae79..98d469620 100644 --- a/compiler/pkg/parser/node.go +++ b/compiler/pkg/parser/node.go @@ -19,18 +19,20 @@ type Node struct { MultipleChildren map[string]Node SingleLink map[string]Node MultipleLink map[string]Node - GraphqlSpec nexus.GraphQLQuerySpec + GraphqlQuerySpec nexus.GraphQLQuerySpec + GraphqlSpec nexus.GraphQLSpec } type NodeHelper struct { - Name string - RestName string - Parents []string - Children map[string]NodeHelperChild // CRD Name => NodeHelperChild - Links map[string]NodeHelperChild // FieldName => NodeHelperChild - RestMappings map[string]string - IsSingleton bool - GraphqlSpec nexus.GraphQLQuerySpec + Name string + RestName string + Parents []string + Children map[string]NodeHelperChild // CRD Name => NodeHelperChild + Links map[string]NodeHelperChild // FieldName => NodeHelperChild + RestMappings map[string]string + IsSingleton bool + GraphqlQuerySpec nexus.GraphQLQuerySpec + GraphqlSpec nexus.GraphQLSpec } type NodeHelperChild struct { @@ -39,6 +41,12 @@ type NodeHelperChild struct { IsNamed bool `json:"isNamed"` } +type NonNexusTypes struct { + Types map[string]ast.Decl + Values []string + ExternalTypes []string +} + func (node *Node) Walk(fn func(node *Node)) { fn(node) diff --git a/compiler/pkg/parser/node_config.go b/compiler/pkg/parser/node_config.go index 2d56b5378..031ac6168 100644 --- a/compiler/pkg/parser/node_config.go +++ b/compiler/pkg/parser/node_config.go @@ -13,6 +13,7 @@ const ( NexusDescriptionAnnotation = "nexus-description" NexusGraphqlAnnotation = "nexus-graphql-query" NexusSecretSpecAnnotation = "nexus-secret-spec" + NexusGraphqlSpecAnnotation = "nexus-graphql-spec" ) func GetNexusSecretSpecAnnotation(pkg Package, name string) (string, bool) { @@ -35,6 +36,10 @@ func GetNexusGraphqlAnnotation(pkg Package, name string) (string, bool) { return getNexusAnnotation(pkg, name, NexusGraphqlAnnotation) } +func GetNexusGraphqlSpecAnnotation(pkg Package, name string) (string, bool) { + return getNexusAnnotation(pkg, name, NexusGraphqlSpecAnnotation) +} + func getNexusAnnotation(pkg Package, name string, annotationName string) (string, bool) { var annotationValue string diff --git a/compiler/pkg/parser/node_parser.go b/compiler/pkg/parser/node_parser.go index 2a8446ab3..20661f500 100644 --- a/compiler/pkg/parser/node_parser.go +++ b/compiler/pkg/parser/node_parser.go @@ -2,10 +2,13 @@ package parser import ( "fmt" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/config" "go/ast" "go/parser" "go/token" + "go/types" "io/fs" + "k8s.io/utils/strings/slices" "path/filepath" "strconv" "strings" @@ -18,12 +21,17 @@ import ( // ParseDSLNodes walks recursively through given path and looks for structs types definitions to add them to graph func ParseDSLNodes(startPath string, baseGroupName string, packages Packages, - graphqlQueries map[string]nexus.GraphQLQuerySpec) map[string]Node { + graphqlQueries map[string]nexus.GraphQLQuerySpec) (map[string]Node, *NonNexusTypes, *token.FileSet) { modulePath := GetModulePath(startPath) rootNodes := make([]string, 0) nodes := make(map[string]Node) pkgsMap := make(map[string]string) + nonNexusTypes := NonNexusTypes{ + Types: map[string]ast.Decl{}, + Values: nil, + } + fileset := token.NewFileSet() err := filepath.Walk(startPath, func(path string, info fs.FileInfo, err error) error { if info.IsDir() { if info.Name() == "build" { @@ -34,7 +42,16 @@ func ParseDSLNodes(startPath string, baseGroupName string, packages Packages, log.Infof("Ignoring vendor directory...") return filepath.SkipDir } - fileset := token.NewFileSet() + //if info.Name() == "cosmos-datamodel" { + // log.Infof("Ignoring cosmos-datamodel directory...") + // return filepath.SkipDir + //} + for _, f := range config.ConfigInstance.IgnoredDirs { + if info.Name() == f { + log.Infof(fmt.Sprintf("Ignoring %v directory from config", f)) + return filepath.SkipDir + } + } pkgs, err := parser.ParseDir(fileset, path, nil, parser.ParseComments) if err != nil { log.Fatalf("Failed to parse directory %s: %v", path, err) @@ -87,15 +104,57 @@ func ParseDSLNodes(startPath string, baseGroupName string, packages Packages, // look for spec in current package annotation = v.Name + "." + annotation } - graphqlSpec, ok := graphqlQueries[annotation] + GraphqlQuerySpec, ok := graphqlQueries[annotation] if ok { - node.GraphqlSpec = graphqlSpec + node.GraphqlQuerySpec = GraphqlQuerySpec } } nodes[crdName] = node + } else { + if !strings.Contains(types.ExprString(typeSpec.Type), "nexus.") && v.Name == "global" { + nonNexusTypes.Types[typeSpec.Name.Name] = decl + } + } + } else { + if !strings.Contains(types.ExprString(typeSpec.Type), "nexus.") && v.Name == "global" { + nonNexusTypes.Types[typeSpec.Name.Name] = decl } } } + if valueSpec, ok := spec.(*ast.ValueSpec); ok { + out, err := util.RenderDecl(decl, fileset) + if err != nil { + return err + } + outStr := out.String() + + // ignore nexus vars + if len(valueSpec.Values) > 0 { + value := valueSpec.Values[0] + if val, ok := value.(*ast.CompositeLit); ok { + if sel, ok := val.Type.(*ast.SelectorExpr); ok { + if types.ExprString(sel.X) == "nexus" { + continue + } + } + } + } + if !slices.Contains(nonNexusTypes.Values, outStr) && v.Name == "global" { + nonNexusTypes.Values = append(nonNexusTypes.Values, outStr) + } + } + } + } + + if _, ok := decl.(*ast.FuncDecl); ok { + out, err := util.RenderDecl(decl, fileset) + if err != nil { + return err + } + outStr := out.String() + + if !slices.Contains(nonNexusTypes.Values, outStr) { + nonNexusTypes.Values = append(nonNexusTypes.Values, outStr) } } } @@ -120,20 +179,28 @@ func ParseDSLNodes(startPath string, baseGroupName string, packages Packages, for _, child := range node.SingleChildren { // if rootNode is a child then remove it from the slice if child.CrdName == rootNode { - rootNodes = append(rootNodes[:i], rootNodes[i+1:]...) + if i+1 >= len(rootNodes) { + rootNodes = rootNodes[:i] + } else { + rootNodes = append(rootNodes[:i], rootNodes[i+1:]...) + } } } for _, child := range node.MultipleChildren { // if rootNode is a named child then remove it from the slice if child.CrdName == rootNode { - rootNodes = append(rootNodes[:i], rootNodes[i+1:]...) + if i+1 >= len(rootNodes) { + rootNodes = rootNodes[:i] + } else { + rootNodes = append(rootNodes[:i], rootNodes[i+1:]...) + } } } } }) } - return buildGraph(nodes, rootNodes, baseGroupName) + return buildGraph(nodes, rootNodes, baseGroupName), &nonNexusTypes, fileset } func buildGraph(nodes map[string]Node, rootNodes []string, baseGroupName string) map[string]Node { @@ -200,13 +267,14 @@ func CreateParentsMap(graph map[string]Node) map[string]NodeHelper { } parents[node.CrdName] = NodeHelper{ - Name: node.Name, - RestName: fmt.Sprintf("%s.%s", node.PkgName, node.Name), - Parents: node.Parents, - Children: children, - Links: links, - IsSingleton: node.IsSingleton, - GraphqlSpec: node.GraphqlSpec, + Name: node.Name, + RestName: fmt.Sprintf("%s.%s", node.PkgName, node.Name), + Parents: node.Parents, + Children: children, + Links: links, + IsSingleton: node.IsSingleton, + GraphqlQuerySpec: node.GraphqlQuerySpec, + GraphqlSpec: node.GraphqlSpec, } }) } @@ -249,8 +317,10 @@ func processNode(node *Node, nodes map[string]Node, baseGroupName string) { if !ok { log.Fatalf("Internal compiler failure: couldn't find node for key %v", key) } - n.Parents = node.Parents - n.Parents = append(n.Parents, node.CrdName) + p := make([]string, len(node.Parents)) + copy(p, node.Parents) + + n.Parents = append(p, node.CrdName) processNode(&n, nodes, baseGroupName) if isNamed { diff --git a/compiler/pkg/parser/node_parser_test.go b/compiler/pkg/parser/node_parser_test.go index 8e8ad4438..35ed1366b 100644 --- a/compiler/pkg/parser/node_parser_test.go +++ b/compiler/pkg/parser/node_parser_test.go @@ -23,7 +23,7 @@ var _ = Describe("Node parser tests", func() { ) BeforeEach(func() { - graph = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, nil, nil) + graph, _, _ = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, nil, nil) root, ok = graph["roots.root.tsm.tanzu.vmware.com"] Expect(ok).To(BeTrue()) }) @@ -147,7 +147,7 @@ var _ = Describe("Node parser tests", func() { }) It("should be able to get graphql info from a field", func() { - graph = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, nil, nil) + graph, _, _ = parser.ParseDSLNodes(exampleDSLPath, baseGroupName, nil, nil) config, ok := graph["roots.root.tsm.tanzu.vmware.com"].SingleChildren["Config"] Expect(ok).To(BeTrue()) diff --git a/compiler/pkg/parser/pkg.go b/compiler/pkg/parser/pkg.go index fec0edc3b..da7b1a73c 100644 --- a/compiler/pkg/parser/pkg.go +++ b/compiler/pkg/parser/pkg.go @@ -35,6 +35,24 @@ type Package struct { FileSet *token.FileSet } +type FieldAnnotation string + +const ( + GRAPHQL_ARGS_ANNOTATION = FieldAnnotation("nexus-graphql-args") + GRAPHQL_ALIAS_NAME_ANNOTATION = FieldAnnotation("nexus-alias-name") + GRAPHQL_ALIAS_TYPE_ANNOTATION = FieldAnnotation("nexus-alias-type") + GRAPHQL_TSM_DIRECTIVE_ANNOTATION = FieldAnnotation("nexus-graphql-tsm-directive") + GRAPHQL_NULLABLE_ANNOTATION = FieldAnnotation("nexus-graphql-nullable") + GRAPHQL_TS_TYPE_ANNOTATION = FieldAnnotation("nexus-graphql-ts-type") + GRAPHQL_JSONENCODED_ANNOTATION = FieldAnnotation("nexus-graphql-jsonencoded") + GRAPHQL_RELATION_NAME = FieldAnnotation("nexus-graphql-relation-name") + GRAPHQL_RELATION_PARAMETERS = FieldAnnotation("nexus-graphql-relation-parameters") + GRAPHQL_RELATION_UUIDKEY = FieldAnnotation("nexus-graphql-relation-uuidkey") + GRAPHQL_TYPE_NAME = FieldAnnotation("nexus-graphql-type-name") + GRAPHQL_PROTOBUF_NAME = FieldAnnotation("nexus-graphql-protobuf-name") + GRAPHQL_PROTOBUF_FILE = FieldAnnotation("nexus-graphql-protobuf-file") +) + // func (p *Package) GetImports() []*ast.ImportSpec // func (p *Package) GetNodes() []*ast.StructType // func (p *Package) GetNexusNodes []*ast.StructType @@ -201,7 +219,7 @@ func IsNexusNode(n *ast.TypeSpec) bool { if val, ok := n.Type.(*ast.StructType); ok { for _, field := range val.Fields.List { typeString := types.ExprString(field.Type) - if typeString == "nexus.Node" || typeString == "nexus.SingletonNode" { + if typeString == "nexus.Node" || typeString == "nexus.SingletonNode" || typeString == "NexusNode" { return true } } @@ -248,7 +266,7 @@ func IsNexusTypeField(f *ast.Field) bool { } typeString := types.ExprString(f.Type) - if typeString == "nexus.Node" || typeString == "nexus.SingletonNode" || typeString == "nexus.ID" { + if typeString == "nexus.Node" || typeString == "nexus.SingletonNode" || typeString == "nexus.ID" || typeString == "NexusNode" { return true } @@ -722,3 +740,91 @@ func (p *Package) ValueSpecToString(t *ast.ValueSpec) (string, error) { } return buf.String(), nil } + +func IsNexusGraphqlNullField(f *ast.Field) bool { + if f == nil { + return false + } + + if f.Tag != nil { + tags := ParseFieldTags(f.Tag.Value) + if val, err := tags.Get(string(GRAPHQL_NULLABLE_ANNOTATION)); err == nil { + if strings.ToLower(val.Name) == "false" { + return false + } + } + } + + return true +} + +// Parser for TSM Integration +// func GetGraphqlArgumentKey(f *ast.Field) string { +// if f == nil { +// return "" +// } + +// if f.Tag != nil { +// tags := ParseFieldTags(f.Tag.Value) +// if val, err := tags.Get("nexus-graphql-arg-key"); err == nil { +// return val.Value() +// } +// } +// return "" +// } + +// func GetGraphqlArgumentValue(f *ast.Field) string { +// if f == nil { +// return "" +// } + +// if f.Tag != nil { +// tags := ParseFieldTags(f.Tag.Value) +// if val, err := tags.Get("nexus-graphql-arg-value"); err == nil { +// return val.Value() +// } +// } +// return "" +// } + +func GetFieldAnnotationString(f *ast.Field, annotation FieldAnnotation) string { + if f == nil { + return "" + } + + if f.Tag != nil { + tags := ParseFieldTags(f.Tag.Value) + if val, err := tags.Get(string(annotation)); err == nil { + return val.String() + } + } + return "" +} + +func GetFieldAnnotationVal(f *ast.Field, annotation FieldAnnotation) string { + if f == nil { + return "" + } + + if f.Tag != nil { + tags := ParseFieldTags(f.Tag.Value) + if val, err := tags.Get(string(annotation)); err == nil { + return val.Value() + } + } + return "" +} + +func IsFieldAnnotationPresent(f *ast.Field, annotation FieldAnnotation) bool { + if f == nil { + return false + } + + if f.Tag != nil { + tags := ParseFieldTags(f.Tag.Value) + if _, err := tags.Get(string(annotation)); err == nil { + return true + } + } + return false +} diff --git a/compiler/pkg/parser/pkg_parser.go b/compiler/pkg/parser/pkg_parser.go index 1611d1180..543e58adb 100644 --- a/compiler/pkg/parser/pkg_parser.go +++ b/compiler/pkg/parser/pkg_parser.go @@ -29,6 +29,10 @@ func ParseDSLPkg(startPath string) Packages { log.Infof("Ignoring vendor directory...") return filepath.SkipDir } + //if info.Name() == "cosmos-datamodel" { + // log.Infof("Ignoring cosmos-datamodel directory...") + // return filepath.SkipDir + //} for _, f := range config.ConfigInstance.IgnoredDirs { if info.Name() == f { @@ -59,7 +63,7 @@ func ParseDSLPkg(startPath string) Packages { FileSet: fileset, Pkg: *v, } - parseGenDecls(v, &pkg) + ParseGenDecls(v, &pkg) packages[pkgImport] = pkg } } @@ -72,7 +76,7 @@ func ParseDSLPkg(startPath string) Packages { return packages } -func parseGenDecls(v *ast.Package, pkg *Package) { +func ParseGenDecls(v *ast.Package, pkg *Package) { sortedKeys := make([]string, 0, len(v.Files)) for k := range v.Files { sortedKeys = append(sortedKeys, k) diff --git a/compiler/pkg/parser/rest/rest_test.go b/compiler/pkg/parser/rest/rest_test.go index 8559cf6bf..779c0a651 100644 --- a/compiler/pkg/parser/rest/rest_test.go +++ b/compiler/pkg/parser/rest/rest_test.go @@ -27,7 +27,7 @@ var _ = Describe("Rest tests", func() { pkgs = parser.ParseDSLPkg(exampleDSLPath) pkg, ok = pkgs["github.com/vmware-tanzu/graph-framework-for-microservices/compiler/example/datamodel/config/gns"] graphqlQueries := parser.ParseGraphqlQuerySpecs(pkgs) - graph := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) + graph, _, _ := parser.ParseDSLNodes(exampleDSLPath, baseGroupName, pkgs, graphqlQueries) parentsMap = parser.CreateParentsMap(graph) Expect(ok).To(BeTrue()) }) @@ -134,7 +134,7 @@ var _ = Describe("Rest tests", func() { } pkgs := parser.ParseDSLPkg("../../../example/test-utils/duplicated-uris-datamodel") - g := parser.ParseDSLNodes("../../../example/test-utils/duplicated-uris-datamodel", baseGroupName, pkgs, nil) + g, _, _ := parser.ParseDSLNodes("../../../example/test-utils/duplicated-uris-datamodel", baseGroupName, pkgs, nil) parents := parser.CreateParentsMap(g) for _, p := range pkgs { diff --git a/compiler/pkg/preparser/preparser.go b/compiler/pkg/preparser/preparser.go new file mode 100644 index 000000000..fd17e37b7 --- /dev/null +++ b/compiler/pkg/preparser/preparser.go @@ -0,0 +1,305 @@ +package preparser + +import ( + "bytes" + "fmt" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/config" + "go/ast" + goParser "go/parser" + "go/printer" + "go/token" + "go/types" + "io/fs" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "text/template" + + cp "github.com/otiai10/copy" + log "github.com/sirupsen/logrus" + "github.com/vmware-tanzu/graph-framework-for-microservices/compiler/pkg/parser" + "golang.org/x/tools/imports" +) + +var pkgImportToPkg = make(map[string]string, 0) + +func Parse(startPath string) map[string][]*parser.Package { + packages := map[string][]*parser.Package{} + modulePath := parser.GetModulePath(startPath) + err := filepath.Walk(startPath, func(path string, info fs.FileInfo, err error) error { + if info.IsDir() { + if info.Name() == "build" { + log.Infof("Ignoring build directory...") + return filepath.SkipDir + } + if info.Name() == "vendor" { + log.Infof("Ignoring vendor directory...") + return filepath.SkipDir + } + //if info.Name() == "cosmos-datamodel" { + // log.Infof("Ignoring cosmos-datamodel directory...") + // return filepath.SkipDir + //} + for _, f := range config.ConfigInstance.IgnoredDirs { + if info.Name() == f { + log.Infof(fmt.Sprintf("Ignoring %v directory from config", f)) + return filepath.SkipDir + } + } + + fileset := token.NewFileSet() + pkgs, err := goParser.ParseDir(fileset, path, nil, goParser.ParseComments) + if err != nil { + log.Fatalf("failed to parse directory %s: %v", path, err) + } + pkgImport := strings.TrimSuffix(strings.ReplaceAll(path, startPath, modulePath), "/") + for _, v := range pkgs { + if v.Name == "nexus" { + log.Infof("Ignoring nexus package...") + continue + } + + if parser.SpecialCharsPresent(v.Name) { + log.Fatalf("Invalid package-name <%v>, special characters are not allowed. Please use only lowercase alphanumeric characters.", v.Name) + } + pkgImportToPkg[pkgImport] = v.Name + + pkg := parser.Package{ + Name: v.Name, + ModPath: modulePath, + FullName: pkgImport, + FileSet: fileset, + Pkg: *v, + } + parser.ParseGenDecls(v, &pkg) + packages[pkg.Name] = append(packages[pkg.Name], &pkg) + } + } + return nil + }) + if err != nil { + log.Fatalf("Failed to parse DSL: %v", err) + } + + detectDuplicates(packages) + + return packages +} + +func detectDuplicates(packages map[string][]*parser.Package) { + for _, v := range packages { + for _, pkg := range v { + nodes := pkg.GetNodes() + nexusNodes := pkg.GetNexusNodes() + + nodes = append(nodes, pkg.GetNonStructTypes()...) + + for _, nexusNode := range nexusNodes { + for _, node := range nodes { + if node.Name.String() == fmt.Sprintf("%sSpec", nexusNode.Name) || + node.Name.String() == fmt.Sprintf("%sList", nexusNode.Name) { + log.Fatalf(`Duplicated type (%s) found in package %s ("%s" is already used by node "%s")`, node.Name, pkg.Name, node.Name, nexusNode.Name) + } + } + } + } + } +} + +func removeImportIdentifierFromFields(file *ast.File, pkg string) *ast.File { + for _, decl := range file.Decls { + genDecl, ok := decl.(*ast.GenDecl) + if !ok { + continue + } + + for _, spec := range genDecl.Specs { + typeSpec, ok := spec.(*ast.TypeSpec) + if !ok { + continue + } + + structType, ok := typeSpec.Type.(*ast.StructType) + if !ok { + continue + } + + for _, field := range structType.Fields.List { + selectorExpr, ok := field.Type.(*ast.SelectorExpr) + if !ok { + continue + } + + if types.ExprString(selectorExpr.X) == "nexus" { + continue + } + + var modify bool + for _, imp := range file.Imports { + pkgImport, _ := strconv.Unquote(imp.Path.Value) + if types.ExprString(selectorExpr.X) == imp.Name.String() { + if val := pkgImportToPkg[pkgImport]; val == pkg { + modify = true + } + } + } + + if types.ExprString(selectorExpr.X) == pkg { + modify = true + } + + if modify { + field.Type = selectorExpr.Sel + } + + } + } + } + return file +} + +func Render(dslDir string, packages map[string][]*parser.Package) error { + for k, pkgs := range packages { + if len(pkgs) == 1 { + continue + } + pkgDir := filepath.Join(dslDir, k) + //TODO: create unique directory (e.g. global may already exist) + err := os.MkdirAll(pkgDir, os.ModePerm) + if err != nil { + return err + } + + created := map[string]int{} + for _, pkg := range pkgs { + for _, file := range pkg.Pkg.Files { + file = removeImportIdentifierFromFields(file, pkg.Name) + + // remove src file + srcFile := pkg.FileSet.Position(file.Package).Filename + err := os.Remove(srcFile) + if err != nil { + return err + } + + filename := filepath.Base(srcFile) + if _, ok := created[filename]; ok { + created[filename]++ + filename = fmt.Sprintf("%d_%s", created[filename], filename) + } + + // render AST to buffer + var buf bytes.Buffer + err = printer.Fprint(&buf, pkg.FileSet, file) + if err != nil { + return err + } + + // format file & organize imports using imports package + out, err := imports.Process(filename, buf.Bytes(), nil) + if err != nil { + return err + } + + // create file and write output + f, err := os.Create(filepath.Join(pkgDir, filename)) + if err != nil { + return err + } + _, err = f.Write(out) + if err != nil { + return err + } + + err = f.Close() + if err != nil { + return err + } + + created[filename] = 0 + } + } + + } + + return nil +} + +func CopyPkgsToBuild(dslDir string, outputDir string) error { + dir, err := ioutil.ReadDir(dslDir) + if err != nil { + return err + } + + for _, f := range dir { + if !f.IsDir() || f.Name() == "build" || f.Name() == "vendor" || + f.Name() == "global" || strings.HasPrefix(f.Name(), ".") { + continue + } + + opt := cp.Options{ + Skip: func(srcinfo os.FileInfo, src, dest string) (bool, error) { + return !strings.HasSuffix(src, ".go"), nil + }, + } + + err := cp.Copy(filepath.Join(dslDir, f.Name()), filepath.Join(outputDir, "model", f.Name()), opt) + if err != nil { + return err + } + } + + return nil +} + +var importsTemplate = `{{range .ImportsToRender}}{{.}} +{{end}}` + +type ImportsTemplateVars struct { + ImportsToRender []string +} + +func RenderImports(packages map[string][]*parser.Package, outputDir string, modPath string) error { + importsTemplateVars := ImportsTemplateVars{ + ImportsToRender: []string{}, + } + + for k, pkgs := range packages { + if k != "global" { + continue + } + + for _, v := range pkgs { + for _, importExpr := range v.GetImportMap() { + importStr := strings.Trim(importExpr, "\"") + if strings.HasPrefix(importStr, v.ModPath+"/global") || + !strings.HasPrefix(importStr, v.ModPath) { + continue + } + + namedImport := "nexus_" + importStr[strings.LastIndex(importStr, "/")+1:] + importsTemplateVars.ImportsToRender = append(importsTemplateVars.ImportsToRender, + fmt.Sprintf("%s %s", namedImport, strings.ReplaceAll(importExpr, v.ModPath, modPath))) + } + } + } + + t, err := template.New("tmpl").Parse(importsTemplate) + if err != nil { + return err + } + + b := bytes.Buffer{} + if err = t.Execute(&b, importsTemplateVars); err != nil { + return err + } + + err = os.WriteFile(filepath.Join(outputDir, "model", "nexus-dm-imports"), b.Bytes(), 0644) + if err != nil { + return err + } + + return nil +} diff --git a/compiler/pkg/util/namers.go b/compiler/pkg/util/namers.go index 6764abaf9..c69f7bc51 100644 --- a/compiler/pkg/util/namers.go +++ b/compiler/pkg/util/namers.go @@ -36,7 +36,7 @@ func GetGroupGoName(baseGroupName string) string { } func GetGroupResourceName(nodeName string) string { - return strings.ToLower(ToPlural(nodeName)) // eg roots + return ToPlural(strings.ToLower(nodeName)) // eg roots } func GetNodeNameTitle(nodeName string) string { diff --git a/compiler/pkg/util/plural.go b/compiler/pkg/util/plural.go index 45755934b..88ff02148 100644 --- a/compiler/pkg/util/plural.go +++ b/compiler/pkg/util/plural.go @@ -14,6 +14,10 @@ limitations under the License. package util var consonants = "bcdfghjklmnpqrstvwxyz" +var exceptions = map[string]string{ + // The type name is already in the plural form + "Endpoints": "Endpoints", +} // ToPlural returns the plural form of the type's name. If the type's name is found // in the exceptions map, the map value is returned. @@ -21,6 +25,10 @@ func ToPlural(t string) string { singular := t var plural string + if plural, ok := exceptions[singular]; ok { + return plural + } + if len(singular) < 2 { return singular } diff --git a/compiler/pkg/util/util.go b/compiler/pkg/util/util.go index 08b29e6ee..6ee539e9d 100644 --- a/compiler/pkg/util/util.go +++ b/compiler/pkg/util/util.go @@ -1,6 +1,10 @@ package util import ( + "bytes" + "go/ast" + "go/printer" + "go/token" "regexp" log "github.com/sirupsen/logrus" @@ -23,3 +27,13 @@ func RemoveSpecialChars(value string) string { } return re.ReplaceAllString(value, "") } + +func RenderDecl(decl ast.Decl, fileset *token.FileSet) (bytes.Buffer, error) { + var buf bytes.Buffer + err := printer.Fprint(&buf, fileset, decl) + if err != nil { + return buf, err + } + + return buf, nil +} diff --git a/compiler/scripts/pin_deps.sh b/compiler/scripts/pin_deps.sh index 10488420b..2918d8945 100755 --- a/compiler/scripts/pin_deps.sh +++ b/compiler/scripts/pin_deps.sh @@ -45,4 +45,3 @@ go mod edit -require k8s.io/klog/v2@v2.70.1 go mod edit -require golang.org/x/net@v0.2.0 go mod edit -require google.golang.org/grpc@v1.51.0 go mod edit -require k8s.io/utils@v0.0.0-20221128185143-99ec85e7a448 - diff --git a/compiler/scripts/pin_graphql_build_version.sh b/compiler/scripts/pin_graphql_build_version.sh index 23393ddf1..7b9b4d7b9 100755 --- a/compiler/scripts/pin_graphql_build_version.sh +++ b/compiler/scripts/pin_graphql_build_version.sh @@ -21,4 +21,3 @@ go mod edit -require golang.org/x/net@v0.2.0 go mod edit -require google.golang.org/grpc@v1.51.0 go mod edit -require k8s.io/utils@v0.0.0-20221128185143-99ec85e7a448 go mod edit -require sigs.k8s.io/controller-runtime@v0.14.1 - diff --git a/nexus/nexus/nexus.go b/nexus/nexus/nexus.go index 79eed10e8..3f843046f 100644 --- a/nexus/nexus/nexus.go +++ b/nexus/nexus/nexus.go @@ -19,6 +19,9 @@ type SingletonNode struct { ID } +// NexusGenericObject type. +type NexusGenericObject struct{} + // HTTPMethod type. type HTTPMethod string @@ -116,3 +119,9 @@ const ( GraphQLQueryApi GraphQlApiType = iota GetMetricsApi ) + +// A GraphQLSpec +type GraphQLSpec struct { + IdName string + IdNullable bool +}