Skip to content

Commit

Permalink
impl: read service config
Browse files Browse the repository at this point in the history
  • Loading branch information
julieqiu committed Nov 4, 2024
1 parent 67f7c88 commit c104b47
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 23 deletions.
28 changes: 20 additions & 8 deletions generator/cmd/protoc-gen-gclient/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,26 @@ func run(r io.Reader, w io.Writer, inputPath, outDir, templateDir string) error
// If capture-input is set, content pass to protoc will be written to a
// sample-input-{timestamp}.bin file, so that protoc does not need to be
// used on future iterations.
if opts.CaptureInput {
if opts.captureInput {
if err := captureInput(genReq); err != nil {
return err
}
}

req, err := protobuf.Translate(genReq, &protobuf.Options{
popts := &protobuf.Options{
OutDir: outDir,
Language: opts.Language,
Language: opts.language,
TemplateDir: templateDir,
})
}
if opts.serviceConfig != "" {
cfg, err := genclient.ReadServiceConfig(opts.serviceConfig)
if err != nil {
return err
}
popts.ServiceConfig = cfg
}

req, err := protobuf.Translate(genReq, popts)
if err != nil {
return err
}
Expand All @@ -102,8 +111,9 @@ func run(r io.Reader, w io.Writer, inputPath, outDir, templateDir string) error
}

type protobufOptions struct {
CaptureInput bool
Language string
captureInput bool
language string
serviceConfig string
}

func parseOpts(optStr string) (*protobufOptions, error) {
Expand All @@ -119,15 +129,17 @@ func parseOpts(optStr string) (*protobufOptions, error) {
continue
}
switch sp[0] {
case "service-config":
opts.serviceConfig = strings.TrimSpace(sp[1])
case "capture-input":
b, err := strconv.ParseBool(sp[1])
if err != nil {
slog.Error("invalid bool in option string, skipping", "option", s)
return nil, err
}
opts.CaptureInput = b
opts.captureInput = b
case "language":
opts.Language = strings.ToLower(strings.TrimSpace(sp[1]))
opts.language = strings.ToLower(strings.TrimSpace(sp[1]))
default:
slog.Warn("unknown option", "option", s)
}
Expand Down
11 changes: 6 additions & 5 deletions generator/devtools/cmd/generate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ import (
)

var (
output = flag.String("out", "output", "the path to the output directory")
language = flag.String("language", "", "the generated language")
protoFiles = flag.String("files", "testdata/googleapis/google/cloud/secretmanager/v1/", "path to protos to generate from")
protoPath = flag.String("proto_path", "testdata/googleapis", "directory in which to search for imports")
language = flag.String("language", "", "the generated language")
output = flag.String("out", "output", "the path to the output directory")
protoFiles = flag.String("files", "testdata/googleapis/google/cloud/secretmanager/v1/", "path to protos to generate from")
protoPath = flag.String("proto_path", "testdata/googleapis", "directory in which to search for imports")
serviceConfig = flag.String("service-config", "testdata/google/cloud/secretmanager/v1/secretmanager_v1.yaml", "path to service config")
)

func main() {
Expand Down Expand Up @@ -59,7 +60,7 @@ func run(language, testdata, input, output string) error {
args := []string{
"-I", testdata,
fmt.Sprintf("--gclient_out=%s", output),
fmt.Sprintf("--gclient_opt=language=%s", language),
fmt.Sprintf("--gclient_opt=language=%s,service-config=%s", language, *serviceConfig),
}
args = append(args, files...)

Expand Down
2 changes: 1 addition & 1 deletion generator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/pb33f/libopenapi v0.18.6
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38
google.golang.org/protobuf v1.35.1
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand All @@ -20,5 +21,4 @@ require (
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240815153524-6ea36470d1bd // indirect
golang.org/x/sync v0.8.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
42 changes: 42 additions & 0 deletions generator/internal/genclient/service_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package genclient

import (
"fmt"
"os"

"google.golang.org/genproto/googleapis/api/serviceconfig"
"gopkg.in/yaml.v3"
)

func ReadServiceConfig(serviceConfigPath string) (*serviceconfig.Service, error) {
y, err := os.ReadFile(serviceConfigPath)
if err != nil {
return nil, fmt.Errorf("error reading service config: %v", err)
}

var cfg serviceconfig.Service
if err := yaml.Unmarshal(y, &cfg); err != nil {
return nil, fmt.Errorf("error unmarshalling service config: %v", err)
}

// An API Service Config will always have a `name` so if it is not populated,
// it's an invalid config.
if cfg.GetName() == "" {
return nil, fmt.Errorf("invalid API service config file %q", serviceConfigPath)
}
return &cfg, nil
}
49 changes: 49 additions & 0 deletions generator/internal/genclient/service_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package genclient

import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/googleapis/google-cloud-rust/generator/internal/sample"
"google.golang.org/genproto/googleapis/api/annotations"
"google.golang.org/genproto/googleapis/api/serviceconfig"
"google.golang.org/protobuf/types/known/apipb"
)

func TestReadServiceConfig(t *testing.T) {
const serviceConfigPath = "../../testdata/googleapis/google/cloud/secretmanager/v1/secretmanager_v1.yaml"
got, err := ReadServiceConfig(serviceConfigPath)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(sample.ServiceConfig, got,
cmpopts.IgnoreUnexported(annotations.HttpRule{}),
cmpopts.IgnoreUnexported(annotations.Http{}),
cmpopts.IgnoreUnexported(apipb.Api{}),
cmpopts.IgnoreUnexported(serviceconfig.AuthenticationRule{}),
cmpopts.IgnoreUnexported(serviceconfig.Authentication{}),
cmpopts.IgnoreUnexported(serviceconfig.BackendRule{}),
cmpopts.IgnoreUnexported(serviceconfig.Backend{}),
cmpopts.IgnoreUnexported(serviceconfig.DocumentationRule{}),
cmpopts.IgnoreUnexported(serviceconfig.Documentation{}),
cmpopts.IgnoreUnexported(serviceconfig.OAuthRequirements{}),
cmpopts.IgnoreUnexported(serviceconfig.Service{}),
); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func TestSimpleObject(t *testing.T) {
}
api, err := makeAPI(model)
if err != nil {
t.Errorf("Error in makeAPI() %q", err)
t.Fatalf("Error in makeAPI() %q", err)
}

checkMessage(t, *api.Messages[0], genclient.Message{
Expand Down
18 changes: 10 additions & 8 deletions generator/internal/genclient/translator/protobuf/protobuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/googleapis/google-cloud-rust/generator/internal/genclient"
"github.com/googleapis/google-cloud-rust/generator/internal/genclient/language"
"google.golang.org/genproto/googleapis/api/serviceconfig"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/pluginpb"
Expand All @@ -47,8 +48,9 @@ const (
type Options struct {
Language string
// Only used for local testing
OutDir string
TemplateDir string
OutDir string
TemplateDir string
ServiceConfig *serviceconfig.Service
}

// Translate translates proto representation into a [genclienGenerateRequest].
Expand Down Expand Up @@ -100,11 +102,12 @@ func makeAPI(req *pluginpb.CodeGeneratorRequest) *genclient.API {
}
state.ServiceByID[service.ID] = service
for _, m := range s.Method {
method := &genclient.Method{}
method.HTTPInfo = parseHTTPInfo(m.GetOptions())
method.Name = m.GetName()
method.InputTypeID = m.GetInputType()
method.OutputTypeID = m.GetOutputType()
method := &genclient.Method{
HTTPInfo: parseHTTPInfo(m.GetOptions()),
Name: m.GetName(),
InputTypeID: m.GetInputType(),
OutputTypeID: m.GetOutputType(),
}
service.Methods = append(service.Methods, method)
}
fileServices = append(fileServices, service)
Expand Down Expand Up @@ -133,7 +136,6 @@ func makeAPI(req *pluginpb.CodeGeneratorRequest) *genclient.API {
}
api.Services = append(api.Services, fileServices...)
}

return api
}

Expand Down
88 changes: 88 additions & 0 deletions generator/internal/sample/sample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package sample provides sample data for testing.
package sample

import (
"google.golang.org/genproto/googleapis/api/annotations"
"google.golang.org/genproto/googleapis/api/serviceconfig"
"google.golang.org/protobuf/types/known/apipb"
)

var ServiceConfig = &serviceconfig.Service{
Name: "secretmanager.googleapis.com",
Title: "Secret Manager API",
Apis: []*apipb.Api{
{
Name: "google.cloud.secretmanager.v1.SecretManagerService",
},
},
Documentation: &serviceconfig.Documentation{
Summary: "Stores sensitive data such as API keys, passwords, and certificates.\nProvides convenience while improving security.",
Rules: []*serviceconfig.DocumentationRule{
{
Selector: "google.cloud.location.Locations.GetLocation",
Description: "Gets information about a location.",
},
{
Selector: "google.cloud.location.Locations.ListLocations",
Description: "Lists information about the supported locations for this service.",
},
},
Overview: "Secret Manager Overview",
},
Backend: &serviceconfig.Backend{
Rules: []*serviceconfig.BackendRule{
{
Selector: "google.cloud.location.Locations.GetLocation",
Deadline: 60,
},
{
Selector: "google.cloud.location.Locations.ListLocations",
Deadline: 60,
},
{
Selector: "google.cloud.secretmanager.v1.SecretManagerService.*",
Deadline: 60,
},
},
},
Http: &annotations.Http{
Rules: []*annotations.HttpRule{
{
Selector: "google.cloud.location.Locations.GetLocation",
},
{
Selector: "google.cloud.location.Locations.ListLocations",
},
},
},
Authentication: &serviceconfig.Authentication{
Rules: []*serviceconfig.AuthenticationRule{
{
Selector: "google.cloud.location.Locations.GetLocation",
Oauth: &serviceconfig.OAuthRequirements{},
},
{
Selector: "google.cloud.location.Locations.ListLocations",
Oauth: &serviceconfig.OAuthRequirements{},
},
{
Selector: "google.cloud.secretmanager.v1.SecretManagerService.*",
Oauth: &serviceconfig.OAuthRequirements{},
},
},
},
}

0 comments on commit c104b47

Please sign in to comment.