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 2317467 commit 9a824f0
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 13 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 @@ -69,7 +69,7 @@ func run(inputPath, outDir, templateDir string) error {
return err
}

if opts.CaptureInput {
if opts.captureInput {
// Remove capture-input param from the captured input
ss := slices.DeleteFunc(strings.Split(genReq.GetParameter(), ","), func(s string) bool {
return strings.Contains(s, "capture-input")
Expand All @@ -84,11 +84,20 @@ func run(inputPath, outDir, templateDir string) error {
}
}

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 @@ -106,8 +115,9 @@ func run(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 @@ -123,15 +133,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
2 changes: 1 addition & 1 deletion generator/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,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 @@ -19,5 +20,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/xerrors v0.0.0-20200804184101-5ec99f83aff1 // 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 unmarshaling 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/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)
}
}
9 changes: 5 additions & 4 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 @@ -29,8 +30,9 @@ import (
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 All @@ -42,8 +44,7 @@ func Translate(req *pluginpb.CodeGeneratorRequest, opts *Options) (*genclient.Ge
}

api := &genclient.API{
//TODO(codyoss): https://github.com/googleapis/google-cloud-rust/issues/38
Name: "secretmanager",
Name: opts.ServiceConfig.GetTitle(),
}
files := req.GetSourceFileDescriptors()
for _, f := range files {
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 9a824f0

Please sign in to comment.