refactor: plugin code structure

This commit is contained in:
debugtalk
2022-03-05 00:34:55 +08:00
parent 1904d404fd
commit 0ede8d7989
27 changed files with 297 additions and 25 deletions

View File

@@ -9,7 +9,7 @@ import (
"github.com/httprunner/hrp/internal/boomer"
"github.com/httprunner/hrp/internal/ga"
pluginInternal "github.com/httprunner/hrp/plugin/inner"
pluginInternal "github.com/httprunner/hrp/plugin/go"
)
func NewBoomer(spawnCount int, spawnRate float64) *HRPBoomer {

View File

@@ -33,4 +33,4 @@ Copyright 2021 debugtalk
* [hrp run](hrp_run.md) - run API test
* [hrp startproject](hrp_startproject.md) - create a scaffold project
###### Auto generated by spf13/cobra on 4-Mar-2022
###### Auto generated by spf13/cobra on 5-Mar-2022

View File

@@ -39,4 +39,4 @@ hrp boom [flags]
* [hrp](hrp.md) - One-stop solution for HTTP(S) testing.
###### Auto generated by spf13/cobra on 4-Mar-2022
###### Auto generated by spf13/cobra on 5-Mar-2022

View File

@@ -23,4 +23,4 @@ hrp har2case $har_path... [flags]
* [hrp](hrp.md) - One-stop solution for HTTP(S) testing.
###### Auto generated by spf13/cobra on 4-Mar-2022
###### Auto generated by spf13/cobra on 5-Mar-2022

View File

@@ -34,4 +34,4 @@ hrp run $path... [flags]
* [hrp](hrp.md) - One-stop solution for HTTP(S) testing.
###### Auto generated by spf13/cobra on 4-Mar-2022
###### Auto generated by spf13/cobra on 5-Mar-2022

View File

@@ -16,4 +16,4 @@ hrp startproject $project_name [flags]
* [hrp](hrp.md) - One-stop solution for HTTP(S) testing.
###### Auto generated by spf13/cobra on 4-Mar-2022
###### Auto generated by spf13/cobra on 5-Mar-2022

View File

@@ -13,7 +13,8 @@ import (
"github.com/rs/zerolog/log"
"github.com/httprunner/hrp/internal/builtin"
pluginInternal "github.com/httprunner/hrp/plugin/inner"
pluginInternal "github.com/httprunner/hrp/plugin/go"
pluginUtils "github.com/httprunner/hrp/plugin/utils"
)
func newParser() *parser {
@@ -252,7 +253,7 @@ func (p *parser) callFunc(funcName string, arguments ...interface{}) (interface{
fn := reflect.ValueOf(function)
// call with builtin function
return pluginInternal.CallFunc(fn, arguments...)
return pluginUtils.CallFunc(fn, arguments...)
}
// merge two variables mapping, the first variables have higher priority

View File

@@ -7,6 +7,8 @@ import (
"runtime"
"github.com/rs/zerolog/log"
pluginUtils "github.com/httprunner/hrp/plugin/utils"
)
// GoPlugin implements golang official plugin
@@ -61,7 +63,7 @@ func (p *GoPlugin) Call(funcName string, args ...interface{}) (interface{}, erro
return nil, fmt.Errorf("function %s not found", funcName)
}
fn := p.cachedFunctions[funcName]
return CallFunc(fn, args...)
return pluginUtils.CallFunc(fn, args...)
}
func (p *GoPlugin) Quit() error {

View File

@@ -9,7 +9,7 @@ import (
"google.golang.org/grpc"
"github.com/httprunner/hrp/internal/json"
"github.com/httprunner/hrp/plugin/proto"
"github.com/httprunner/hrp/plugin/go/proto"
)
// functionGRPCClient runs on the host side, it implements FuncCaller interface

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.27.1
// protoc v3.19.4
// source: plugin/proto/debugtalk.proto
@@ -228,10 +228,9 @@ var file_plugin_proto_debugtalk_proto_rawDesc = []byte{
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x12, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x2f,
0x68, 0x72, 0x70, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x11, 0x5a, 0x0f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (

View File

@@ -1,4 +1,8 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.19.4
// source: plugin/proto/debugtalk.proto
package proto

View File

@@ -9,7 +9,8 @@ import (
"github.com/hashicorp/go-plugin"
"github.com/rs/zerolog/log"
pluginInternal "github.com/httprunner/hrp/plugin/inner"
pluginInternal "github.com/httprunner/hrp/plugin/go"
pluginUtils "github.com/httprunner/hrp/plugin/utils"
)
// functionsMap stores plugin functions
@@ -37,7 +38,7 @@ func (p *functionPlugin) Call(funcName string, args ...interface{}) (interface{}
return nil, fmt.Errorf("function %s not found", funcName)
}
return pluginInternal.CallFunc(fn, args...)
return pluginUtils.CallFunc(fn, args...)
}
var functions = make(functionsMap)

View File

@@ -1,10 +1,62 @@
## Updating the Protocol
# Updating the Protocol
If you update the protocol buffers file, you can regenerate the file using the following command from the project root directory. You do not need to run this if you're just using the plugin.
For Go:
## For Go
### Install dependencies
ref: https://www.grpc.io/docs/languages/go/quickstart/
Install the protocol compiler plugins for Go using the following commands:
```bash
$ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative plugin/proto/debugtalk.proto
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
```
Update your PATH so that the protoc compiler can find the plugins:
```bash
$ export PATH="$PATH:$(go env GOPATH)/bin"
```
### Generate gRPC code
```bash
$ protoc --go_out=. --go-grpc_out=. plugin/proto/debugtalk.proto
```
This will generate two go files in `plugin/go/proto` folder:
- debugtalk.pb.go
- debugtalk_grpc.pb.go
## For Python
### Install dependencies
ref: https://www.grpc.io/docs/languages/python/quickstart/
Install gRPC:
```bash
$ pip3 install grpcio
```
Install gRPC tools:
```bash
$ pip3 install grpcio-tools
```
### Generate gRPC code
```bash
$ python3 -m grpc_tools.protoc -I plugin/proto --python_out=plugin/python/ --grpc_python_out=plugin/python/ plugin/proto/debugtalk.proto
```
This will generate two python files in `plugin/python` folder:
- debugtalk_pb2.py
- debugtalk_pb2_grpc.py

View File

@@ -1,7 +1,7 @@
syntax = "proto3";
package proto;
option go_package = "github.com/httprunner/hrp/plugin/proto";
option go_package = "plugin/go/proto";
message Empty {}

View File

@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: debugtalk.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x64\x65\x62ugtalk.proto\x12\x05proto\"\x07\n\x05\x45mpty\"!\n\x10GetNamesResponse\x12\r\n\x05names\x18\x01 \x03(\t\")\n\x0b\x43\x61llRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x61rgs\x18\x02 \x01(\x0c\"\x1d\n\x0c\x43\x61llResponse\x12\r\n\x05value\x18\x01 \x01(\x0c\x32o\n\tDebugTalk\x12\x31\n\x08GetNames\x12\x0c.proto.Empty\x1a\x17.proto.GetNamesResponse\x12/\n\x04\x43\x61ll\x12\x12.proto.CallRequest\x1a\x13.proto.CallResponseB\x11Z\x0fplugin/go/protob\x06proto3')
_EMPTY = DESCRIPTOR.message_types_by_name['Empty']
_GETNAMESRESPONSE = DESCRIPTOR.message_types_by_name['GetNamesResponse']
_CALLREQUEST = DESCRIPTOR.message_types_by_name['CallRequest']
_CALLRESPONSE = DESCRIPTOR.message_types_by_name['CallResponse']
Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), {
'DESCRIPTOR' : _EMPTY,
'__module__' : 'debugtalk_pb2'
# @@protoc_insertion_point(class_scope:proto.Empty)
})
_sym_db.RegisterMessage(Empty)
GetNamesResponse = _reflection.GeneratedProtocolMessageType('GetNamesResponse', (_message.Message,), {
'DESCRIPTOR' : _GETNAMESRESPONSE,
'__module__' : 'debugtalk_pb2'
# @@protoc_insertion_point(class_scope:proto.GetNamesResponse)
})
_sym_db.RegisterMessage(GetNamesResponse)
CallRequest = _reflection.GeneratedProtocolMessageType('CallRequest', (_message.Message,), {
'DESCRIPTOR' : _CALLREQUEST,
'__module__' : 'debugtalk_pb2'
# @@protoc_insertion_point(class_scope:proto.CallRequest)
})
_sym_db.RegisterMessage(CallRequest)
CallResponse = _reflection.GeneratedProtocolMessageType('CallResponse', (_message.Message,), {
'DESCRIPTOR' : _CALLRESPONSE,
'__module__' : 'debugtalk_pb2'
# @@protoc_insertion_point(class_scope:proto.CallResponse)
})
_sym_db.RegisterMessage(CallResponse)
_DEBUGTALK = DESCRIPTOR.services_by_name['DebugTalk']
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'Z\017plugin/go/proto'
_EMPTY._serialized_start=26
_EMPTY._serialized_end=33
_GETNAMESRESPONSE._serialized_start=35
_GETNAMESRESPONSE._serialized_end=68
_CALLREQUEST._serialized_start=70
_CALLREQUEST._serialized_end=111
_CALLRESPONSE._serialized_start=113
_CALLRESPONSE._serialized_end=142
_DEBUGTALK._serialized_start=144
_DEBUGTALK._serialized_end=255
# @@protoc_insertion_point(module_scope)

View File

@@ -0,0 +1,99 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import debugtalk_pb2 as debugtalk__pb2
class DebugTalkStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetNames = channel.unary_unary(
'/proto.DebugTalk/GetNames',
request_serializer=debugtalk__pb2.Empty.SerializeToString,
response_deserializer=debugtalk__pb2.GetNamesResponse.FromString,
)
self.Call = channel.unary_unary(
'/proto.DebugTalk/Call',
request_serializer=debugtalk__pb2.CallRequest.SerializeToString,
response_deserializer=debugtalk__pb2.CallResponse.FromString,
)
class DebugTalkServicer(object):
"""Missing associated documentation comment in .proto file."""
def GetNames(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Call(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_DebugTalkServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetNames': grpc.unary_unary_rpc_method_handler(
servicer.GetNames,
request_deserializer=debugtalk__pb2.Empty.FromString,
response_serializer=debugtalk__pb2.GetNamesResponse.SerializeToString,
),
'Call': grpc.unary_unary_rpc_method_handler(
servicer.Call,
request_deserializer=debugtalk__pb2.CallRequest.FromString,
response_serializer=debugtalk__pb2.CallResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'proto.DebugTalk', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class DebugTalk(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def GetNames(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/proto.DebugTalk/GetNames',
debugtalk__pb2.Empty.SerializeToString,
debugtalk__pb2.GetNamesResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def Call(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/proto.DebugTalk/Call',
debugtalk__pb2.CallRequest.SerializeToString,
debugtalk__pb2.CallResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

46
plugin/python/plugin.py Normal file
View File

@@ -0,0 +1,46 @@
from concurrent import futures
import sys
import time
import grpc
import debugtalk_pb2
import debugtalk_pb2_grpc
from grpc_health.v1.health import HealthServicer
from grpc_health.v1 import health_pb2, health_pb2_grpc
class DebugTalkServicer(debugtalk_pb2_grpc.DebugTalkServicer):
"""Implementation of DebugTalk service."""
def GetNames(self, request, context):
result = debugtalk_pb2.GetNamesResponse()
return result
def Call(self, request, context):
return
def serve():
# We need to build a health service to work with go-plugin
health = HealthServicer()
health.set("plugin", health_pb2.HealthCheckResponse.ServingStatus.Value('SERVING'))
# Start the server.
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
debugtalk_pb2_grpc.add_DebugTalkServicer_to_server(DebugTalkServicer(), server)
health_pb2_grpc.add_HealthServicer_to_server(health, server)
server.add_insecure_port('127.0.0.1:1234')
server.start()
# Output information
print("1|1|tcp|127.0.0.1:1234|grpc")
sys.stdout.flush()
try:
while True:
time.sleep(60 * 60 * 24)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()

View File

@@ -1,4 +1,4 @@
package pluginInternal
package pluginUtils
import (
"fmt"

View File

@@ -1,4 +1,4 @@
package pluginInternal
package pluginUtils
import (
"errors"

View File

@@ -32,7 +32,7 @@ import (
"github.com/httprunner/hrp/internal/builtin"
"github.com/httprunner/hrp/internal/ga"
"github.com/httprunner/hrp/internal/json"
pluginInternal "github.com/httprunner/hrp/plugin/inner"
pluginInternal "github.com/httprunner/hrp/plugin/go"
)
const (