Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add functionality to export proto files #475

Merged
merged 9 commits into from
Jul 12, 2024

Conversation

Eitol
Copy link
Contributor

@Eitol Eitol commented Jul 10, 2024

Feature Description:

Add a new option --proto-out-dir to grpcurl that allows users to generate .proto files for listed, described, or invoked elements and their transitive dependencies.

Functionality:

When using the list and describe verbs, the listed or described elements and their transitive dependencies will be written as .proto files in the specified directory.

Proposed Implementation:
Add a new flag:

protoOut = flags.String("proto-out-dir", "", "The name of a directory where the generated .proto files will be written.")

Use Case:
This feature will be useful for users who need to generate .proto files from gRPC services, especially when working with services that don't have readily available .proto files or when dealing with dynamically generated services.

Tested with the starlink gRPC server.

image

TEST: OK

image

closes #474
closes #206

Added a new function, `WriteProtoFiles` in `desc_source.go` which is used to generate .proto files. The process involves resolving symbols from the descriptor source and writing their definitions to a designated output directory. The corresponding flag `--proto-out` has been included in `grpcurl.go` to allow users to specify the directory path.
@Eitol Eitol changed the title Add functionality to export proto files feat: Add functionality to export proto files Jul 10, 2024
Eitol added 2 commits July 10, 2024 09:05
The code for file creation and error handling in desc_source.go has been refactored. Previously, the file closure operation was executed irrespective of whether the file was created successfully or not. Now, the file will only be closed if it was successfully created, improving error handling.
The command for exporting proto files and setting the output directory has been updated from 'proto-out' to 'proto-out-dir'. This change has been made both in the README and the grpcurl go file. This makes the command name more descriptive, accurately reflecting its functionality.
@Eitol Eitol mentioned this pull request Jul 10, 2024
Copy link
Member

@dragonsinth dragonsinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to me, @jhump wdyt?

desc_source.go Outdated Show resolved Hide resolved
Eitol added 3 commits July 10, 2024 11:05
The file close operation has been moved within the error handling of the 'PrintProtoFile' function. Previously, it was being executed before this function, now it's executed immediately after. Moreover, an additional close operation has been added after the function success ensuring the file is properly closed in all scenarios.
The grpcurl commands for exporting proto files and protoset files in the README are updated. The IP address has been changed to localhost and port number to '8787'. Also, the service name is adjusted to 'my.custom.server.Service'. Instructions for use of specific command options are added for enhanced clarity.
desc_source.go Outdated
Comment on lines 325 to 327
if f != nil {
_ = f.Close()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should be able to omit this block, if err is non-nil, f will be nil

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

desc_source.go Outdated
_ = f.Close()
}
return fmt.Errorf("failed to create file %q: %v", filePath, err)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

immediately after this block, you should probably defer f.Close()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to scope it sometimes:

for _, fd := range allFilesSlice {
	fdFQName := fd.GetFullyQualifiedName()
	dirPath := filepath.Dir(fdFQName)
	outFilepath := filepath.Join(outProtoDirPath, dirPath)
	if err := os.MkdirAll(outFilepath, 0755); err != nil {
		return fmt.Errorf("failed to create directory %q: %v", outFilepath, err)
	}
	fileName := filepath.Base(fdFQName)
	filePath := filepath.Join(outFilepath, fileName)
	err := func() error {
		f, err := os.Create(filePath)
		if err != nil {
			return fmt.Errorf("failed to create")
		}
		defer f.Close()
		if err := pr.PrintProtoFile(fd, f); err != nil {
			return fmt.Errorf("failed to write")
		}
		if err := f.Close(); err != nil {
			return fmt.Errorf("failed to close")
		}
		return nil
	}()
	if err != nil {
		return fmt.Errorf("file %q: %w", filePath, err)
	}
}
return nil

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^^ yeah this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ready

desc_source.go Outdated
Comment on lines 330 to 334
if err := pr.PrintProtoFile(fd, f); err != nil {
_ = f.Close()
return fmt.Errorf("failed to write file %q: %v", filePath, err)
}
_ = f.Close()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You actually want to error check the close as well. Something like:

err = pr.PrintProtoFile(fd, f)
if err == nil {
  err = f.Close()
}
// do the error check now

you also don't need the final close if you deferred close earlier

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ready

The code responsible for error handling during file creation in the desc_source.go file has been streamlined. This modification simplifies the code by reducing unnecessary condition checks and redundant file closure action after an error has occurred.
@Eitol
Copy link
Contributor Author

Eitol commented Jul 10, 2024

@dragonsinth hello. Is there anything else to complete?

The file writing process for protobuf files has been extracted into a new function called writeProtoFile(). This refactoring simplifies the main function. The code is cleaner and more manageable this way, improving maintainability and readability.
return fmt.Errorf("failed to write proto file: %v", err)
}
return nil
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do one more pass on this, I have a few changes:

  • simplify filepath calculations and naming
  • improve errors with filename and error wrapping
  • 0777 so the system level umask can take effect
func writeProtoFile(outProtoDirPath string, fd *desc.FileDescriptor, pr *protoprint.Printer) error {
	outFile := filepath.Join(outProtoDirPath, fd.GetFullyQualifiedName())
	outDir := filepath.Dir(outFile)
	if err := os.MkdirAll(outDir, 0777); err != nil {
		return fmt.Errorf("failed to create directory %q: %w", outDir, err)
	}

	f, err := os.Create(outFile)
	if err != nil {
		return fmt.Errorf("failed to create proto file %q: %w", outFile, err)
	}
	defer f.Close()
	if err := pr.PrintProtoFile(fd, f); err != nil {
		return fmt.Errorf("failed to write proto file %q: %w", outFile, err)
	}
	return nil
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ready

Streamlined the writeProtoFile function in desc_source.go file. Simplified path calculations and improved error messages for file-creation functions, making it easier to trace the exact point of failure and enhance the debugging process.
@dragonsinth dragonsinth merged commit 46c38b3 into fullstorydev:master Jul 12, 2024
3 checks passed
@jhump
Copy link
Contributor

jhump commented Jul 22, 2024

Seems reasonable to me, @jhump wdyt?

Sorry for lack of reply. I've been on a family vacation. FWIW, looks good to me, too 👍.

@rrfheff
Copy link

rrfheff commented Aug 21, 2024

keen to use this feature too, when will we release it?

@victorphamdeveloper
Copy link

Keen to use this feature too. Wonder how people deal with this without this feature

@jhump
Copy link
Contributor

jhump commented Dec 16, 2024

@rrfheffm, @victorphamdeveloper, looks like this was included in the 1.9.2 release the other week.

bungle added a commit to Kong/kong that referenced this pull request Jan 28, 2025
### Summary

### v1.9.2

- update core Go version in go.mod to 1.21
- chore: update to Golang 1.23 (fullstorydev/grpcurl#485)
- Update README.md (fullstorydev/grpcurl#353)
- Remove custom dialer in order to use the default grpc-go dialer, which supports proxies. (fullstorydev/grpcurl#480)
- makefile updates (fullstorydev/grpcurl#484)
- feat: Add functionality to export proto files (fullstorydev/grpcurl#475)
- Bump google.golang.org/protobuf from 1.34.1 to 1.34.2 (fullstorydev/grpcurl#470)
- add 32bit arm build targets (fullstorydev/grpcurl#461)
- Bump google.golang.org/protobuf from 1.34.0 to 1.34.1 (fullstorydev/grpcurl#465)
- feat: introduce transparent client side health check (fullstorydev/grpcurl#463)
- Bump google.golang.org/protobuf (fullstorydev/grpcurl#460)
- Bump golang.org/x/net from 0.22.0 to 0.23.0 (fullstorydev/grpcurl#458)

### v1.9.1

- Update Dockerfile to use Go v1.21 (fullstorydev/grpcurl#455)
- chore: fix some typos in comments (fullstorydev/grpcurl#454)

### v1.9.0

- Use latest protoreflect to fix some bugs (fullstorydev/grpcurl#453)
- Brand name update (fullstorydev/grpcurl#452)
- Bump github.com/golang/protobuf from 1.5.3 to 1.5.4 (fullstorydev/grpcurl#448)
- goreleaser: bump version & add nfmp support fullstorydev/grpcurl#440)
- Enable xDS credentials (fullstorydev/grpcurl#424)
- Bump github.com/jhump/protoreflect from 1.15.5 to 1.15.6 (fullstorydev/grpcurl#446)
- Use localhost for default unix domain socket authority (fullstorydev/grpcurl#445)
- Bump github.com/jhump/protoreflect from 1.15.4 to 1.15.5 (fullstorydev/grpcurl#443)
- Added initial support for -t flag to show timings (fullstorydev/grpcurl#428)
- Expand the documentation of -max-time to clarify this sets the RPC timeout (fullstorydev/grpcurl#435)
- Bump github.com/jhump/protoreflect from 1.15.3 to 1.15.4 (fullstorydev/grpcurl#436)
- Bump google.golang.org/protobuf from 1.31.0 to 1.32.0 (fullstorydev/grpcurl#437)
- indent: rip out old go 1.9 support
- Bump golang.google.org/grpc to v1.57.1 (fullstorydev/grpcurl#427)
- Update Tarball URL used by Homebrew (fullstorydev/grpcurl#421)

#### v1.8.9

- Disable CGO for improved compatibility across distros (fullstorydev/grpcurl#420)
- Bump golang.org/x/net from 0.9.0 to 0.17.0 (fullstorydev/grpcurl#419)
- SIGSEGV: panic: runtime error: invalid memory address or nil pointer dereference in protoreflect (fullstorydev/grpcurl#416)
- Added alts credential option (fullstorydev/grpcurl#341)

#### v1.8.8

- Update go.mod, goreleaser for v1.8.8 (fullstorydev/grpcurl#413)
- Run tests on Go 1.21 (fullstorydev/grpcurl#408)
- Update protoreflect v1.15.2 and grpc v1.57.0 (fullstorydev/grpcurl#406)
- Use grpc.reflection.v1.ServerReflection (fullstorydev/grpcurl#407)
- Bump google.golang.org/protobuf from 1.30.0 to 1.31.0 (fullstorydev/grpcurl#401)
- Bump google.golang.org/grpc from 1.55.0 to 1.56.1 (fullstorydev/grpcurl#400)
- Fix issues with error details (fullstorydev/grpcurl#379)
- fix nil-dereference panic (fullstorydev/grpcurl#395)
- Bump google.golang.org/grpc from 1.54.0 to 1.55.0 (fullstorydev/grpcurl#390)
- Add "checkgenerate" make target to CI (fullstorydev/grpcurl#385)
- Bump google.golang.org/grpc from 1.53.0 to 1.54.0 (fullstorydev/grpcurl#383)
- Bump google.golang.org/protobuf from 1.29.1 to 1.30.0 (fullstorydev/grpcurl#378)
- Bump google.golang.org/protobuf from 1.29.0 to 1.29.1 (fullstorydev/grpcurl#376)
- Bump google.golang.org/protobuf from 1.28.1 to 1.29.0 (fullstorydev/grpcurl#375)
- Bump github.com/golang/protobuf from 1.5.2 to 1.5.3 (fullstorydev/grpcurl#374)
- Bump google.golang.org/grpc from 1.52.3 to 1.53.0 (fullstorydev/grpcurl#370)
- Install the CodeSee workflow. Learn more at https://docs.codesee.io (fullstorydev/grpcurl#368)
- Bump google.golang.org/grpc from 1.51.0 to 1.52.3 (fullstorydev/grpcurl#365)
- Bump github.com/jhump/protoreflect from 1.14.0 to 1.14.1 (fullstorydev/grpcurl#361)
- Bump google.golang.org/grpc from 1.50.1 to 1.51.0 (fullstorydev/grpcurl#348)
- fix funcname in comment (fullstorydev/grpcurl#346)
- Bump github.com/jhump/protoreflect from 1.13.0 to 1.14.0 (fullstorydev/grpcurl#343)
- Bump google.golang.org/grpc from 1.50.0 to 1.50.1 (fullstorydev/grpcurl#338)
- Bump google.golang.org/grpc from 1.49.0 to 1.50.0 (fullstorydev/grpcurl#336)
- Bump github.com/jhump/protoreflect from 1.12.0 to 1.13.0 (fullstorydev/grpcurl#335)
- Bump google.golang.org/grpc from 1.48.0 to 1.49.0 (fullstorydev/grpcurl#330)
- fixup release process (fullstorydev/grpcurl#328)

#### v1.8.7

- Unix sockets for windows
- Lots of dependency version updates
- Support for Go 1.18
- Add go 1.18 support; set Dockerfile to go 1.18 (fullstorydev/grpcurl#325)
- build alpine base image (fullstorydev/grpcurl#311)
- fix some typos (fullstorydev/grpcurl#314)
- Bump google.golang.org/grpc from 1.47.0 to 1.48.0 (fullstorydev/grpcurl#324)
- Adding power(ppc64le) arch support (fullstorydev/grpcurl#296)
- Enable support for Unix sockets for Windows by enabling -unix flag for Windows builds. (fullstorydev/grpcurl#317)
- Bump google.golang.org/grpc from 1.46.2 to 1.47.0 (fullstorydev/grpcurl#315)
- Bump github.com/jhump/protoreflect from 1.10.3 to 1.12.0 (fullstorydev/grpcurl#294)
- Bump google.golang.org/grpc from 1.44.0 to 1.46.2 (fullstorydev/grpcurl#310)
- Bump google.golang.org/protobuf from 1.27.1 to 1.28.0 (fullstorydev/grpcurl#298)
- use newer goreleaser (fullstorydev/grpcurl#293)
- Restore support for linux/s390x for the next release. (fullstorydev/grpcurl#292)
- Bump google.golang.org/protobuf from 1.26.0 to 1.27.1 (fullstorydev/grpcurl#288)

#### v1.8.6

- Some bugs have been addressed in the library used to parse proto source files.
  Previously grpcurl would accept proto source files that could not actually be compiled with protoc.
  The converse could also happen: grpcurl could reject some proto source files that could successfully
  be compiled with protoc. More details can be found in the release notes for the changes to
  the protoparse library, versions v1.10.2 and v1.10.3.
- Some implementations of the server reflection service have been observed to return multiple
  (even superfluous) file descriptors, in response to requests made by grpcurl. These extra files,
  if not returned in a particular order, would cause grpcurl to report an error that the service
  or method to be invoked could be not be resolved. The reflection client in grpcurl is now more
  robust to this condition and can handle responses with file descriptors in any order, so it should
  be interoperable with a larger variety of servers.
- When a request message includes a field of type google.protobuf.Value and a value for that field
  that was a JSON array, grpcurl would incorrectly interpret the JSON array as if it were a single
  atomic value, the last value that was in the array. This has been fixed.
- When a response message includes non-printable characters or code points outside the ASCII 7-bit
  range in the name of a field in a JSON object, it could be improperly encoded with escape characters
  that are not valid JSON. Standard tools/libraries could then fail to parse the JSON output from grpcurl.
  This has been fixed.

Signed-off-by: Aapo Talvensaari <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add --proto-out-dir option to generate .proto files Proto generation
5 participants