Is the instructions for making python plugins in the go-plugin repo outdated?

Sorry if this isn’t the right place to be posting about this. I have a project which uses the go-plugin package. I recently tried making a Python plugin by following the instructions in the docs folder for this package and I get an error:

plugin.stdio: received EOF, stopping recv loop: err="rpc error: code = Unimplemented desc = Method not found!"

I tried cloning the repo and running the python plugin example provided and I get the same error. Looking at the source code for golang based plugins, I noticed that plugins register many gRPC services that are not present for the python equivalent:

// ServerProtocol impl.
func (s *GRPCServer) Init() error {
	// Create our server
	var opts []grpc.ServerOption
	if s.TLS != nil {
		opts = append(opts, grpc.Creds(credentials.NewTLS(s.TLS)))
	s.server = s.Server(opts)

	// Register the health service
	healthCheck := health.NewServer()
		GRPCServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
	grpc_health_v1.RegisterHealthServer(s.server, healthCheck)

	// Register the reflection service
	reflection.Register(s.server) // reflection not in python

	// Register the broker service
	brokerServer := newGRPCBrokerServer()
	plugin.RegisterGRPCBrokerServer(s.server, brokerServer) // broker not in python = newGRPCBroker(brokerServer, s.TLS)

	// Register the controller
	controllerServer := &grpcControllerServer{server: s} 
	plugin.RegisterGRPCControllerServer(s.server, controllerServer) // controller not in python

	// Register the stdio service
	s.stdioServer = newGRPCStdioServer(s.logger, s.Stdout, s.Stderr)
	plugin.RegisterGRPCStdioServer(s.server, s.stdioServer) // stdio not in python

The gRPC client at the least seems to interact with Stdio and Broker services:

// newGRPCClient creates a new GRPCClient. The Client argument is expected
// to be successfully started already with a lock held.
func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) {
	conn, err := dialGRPCConn(c.config.TLSConfig, c.dialer, c.config.GRPCDialOptions...)
	if err != nil {
		return nil, err

	// Start the broker.
	brokerGRPCClient := newGRPCBrokerClient(conn)
	broker := newGRPCBroker(brokerGRPCClient, c.config.TLSConfig)
	go broker.Run()
	go brokerGRPCClient.StartStream()

	// Start the stdio client
	stdioClient, err := newGRPCStdioClient(doneCtx, c.logger.Named("stdio"), conn)
	if err != nil {
		return nil, err
	go stdioClient.Run(c.config.SyncStdout, c.config.SyncStderr)

	cl := &GRPCClient{
		Conn:       conn,
		Plugins:    c.config.Plugins,
		doneCtx:    doneCtx,
		broker:     broker,
		controller: plugin.NewGRPCControllerClient(conn),

	return cl, nil

What I’m asking is, should there be gRPC Broker and Stdio implementations in python for python plugins to work?

Hi @SSSOCPaulCote :wave: Thanks for raising this.

While there may be folks following this section of HashiCorp Discuss that could potentially answer this question, admittedly I’m not sure if any non-Go developers or go-plugin maintainers follow here since Terraform provider development is mainly based on Go and most developers are using the higher level frameworks for provider development. You may find that raising an issue in the go-plugin GitHub repository is the best path forward to getting clarity in this situation since ultimately it sounds like the documentation within that project may need updates as well. It appears like you already did create a GitHub issue, Is the documentation for making non-go plugins outdated? · Issue #212 · hashicorp/go-plugin · GitHub, so hopefully someone closer to that project or that particular documentation can comment appropriately there.

1 Like

Alright sounds good. Thank you for responding :pray: