-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add module proto grpc interface (#844)
- Loading branch information
Showing
7 changed files
with
490 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,91 @@ | ||
package modules | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/go-plugin" | ||
"github.com/pkg/errors" | ||
"google.golang.org/grpc" | ||
|
||
v1 "kusionstack.io/kusion/pkg/apis/core/v1" | ||
"kusionstack.io/kusion/pkg/modules/proto" | ||
) | ||
|
||
// Generator is an interface for things that can generate Intent from input | ||
// configurations. | ||
const PluginKey = "module-default" | ||
|
||
// HandshakeConfig is a common handshake that is shared by plugin and host. | ||
var HandshakeConfig = plugin.HandshakeConfig{ | ||
ProtocolVersion: 1, | ||
MagicCookieKey: "MODULE_PLUGIN", | ||
MagicCookieValue: "ON", | ||
} | ||
|
||
// Generator is an interface for things that can generate Intent from input configurations. | ||
// todo it's for built-in generators and we should consider to convert it to a general Module interface | ||
type Generator interface { | ||
// Generate performs the intent generate operation. | ||
Generate(intent *v1.Intent) error | ||
} | ||
|
||
// Module is the interface that we're exposing as a kusion module plugin. | ||
type Module interface { | ||
Generate(req *proto.GeneratorRequest) (*proto.GeneratorResponse, error) | ||
} | ||
|
||
// NewGeneratorFunc is a function that returns a Generator. | ||
type NewGeneratorFunc func() (Generator, error) | ||
|
||
// GeneratorRequest defines the request of generators. | ||
type GeneratorRequest struct { | ||
// Project represents the project name | ||
Project string | ||
// Stack represents the stack name | ||
Stack string | ||
// App represents the application name | ||
App string | ||
// Type represents the module type | ||
Type string | ||
// Config is the module inputs of the specific module type | ||
Config v1.GenericConfig | ||
// TerraformConfig is the collection of provider configs for the terraform runtime. | ||
TerraformConfig v1.TerraformConfig | ||
type GRPCClient struct { | ||
client proto.ModuleClient | ||
} | ||
|
||
func (c *GRPCClient) Generate(req *proto.GeneratorRequest) (*proto.GeneratorResponse, error) { | ||
return c.client.Generate(context.Background(), req) | ||
} | ||
|
||
type GRPCServer struct { | ||
// This is the real implementation | ||
Impl Module | ||
proto.UnimplementedModuleServer | ||
} | ||
|
||
func (s *GRPCServer) Generate(ctx context.Context, req *proto.GeneratorRequest) (res *proto.GeneratorResponse, err error) { | ||
defer func() { | ||
if e := recover(); e != nil { | ||
err = errors.WithStack(err) | ||
res = &proto.GeneratorResponse{} | ||
} | ||
}() | ||
res, err = s.Impl.Generate(req) | ||
return | ||
} | ||
|
||
type GRPCPlugin struct { | ||
// GRPCPlugin must still implement the Plugin interface | ||
plugin.Plugin | ||
// Concrete implementation, written in Go. This is only used for plugins that are written in Go. | ||
Impl Module | ||
} | ||
|
||
// GRPCServer is going to be invoked by the go-plugin framework | ||
func (p *GRPCPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error { | ||
proto.RegisterModuleServer(s, &GRPCServer{Impl: p.Impl}) | ||
return nil | ||
} | ||
|
||
// GRPCClient is going to be invoked by the go-plugin framework | ||
func (p *GRPCPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) { | ||
return &GRPCClient{client: proto.NewModuleClient(c)}, nil | ||
} | ||
|
||
func StartModule(module Module) { | ||
plugin.Serve(&plugin.ServeConfig{ | ||
HandshakeConfig: HandshakeConfig, | ||
Plugins: map[string]plugin.Plugin{ | ||
PluginKey: &GRPCPlugin{Impl: module}, | ||
}, | ||
|
||
// A non-nil value here enables gRPC serving for this plugin... | ||
GRPCServer: plugin.DefaultGRPCServer, | ||
}) | ||
} |
Oops, something went wrong.