Add prototype of pipeline api using connect

This includes refactoring of the http listener to use
a custom mux.
This commit is contained in:
2022-12-24 19:45:25 -07:00
parent 08e8104cd9
commit cd098d794d
10 changed files with 394 additions and 9 deletions
+4 -1
View File
@@ -4,9 +4,12 @@ go 1.19
require (
git.ohea.xyz/golang/config v0.0.0-20220915224621-b9debd233173
github.com/bufbuild/connect-go v1.4.1
github.com/go-git/go-git/v5 v5.4.3-0.20220529141257-bc1f419cebcf
github.com/go-playground/webhooks/v6 v6.0.1
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
golang.org/x/net v0.2.0
google.golang.org/protobuf v1.28.1
nhooyr.io/websocket v1.8.7
)
@@ -32,8 +35,8 @@ require (
github.com/xanzy/ssh-agent v0.3.2 // indirect
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.2.0 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/tools v0.1.12 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+3 -1
View File
@@ -241,6 +241,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bufbuild/connect-go v1.4.1 h1:6usL3JGjKhxQpvDlizP7u8VfjAr1JkckcAUbrdcbgNY=
github.com/bufbuild/connect-go v1.4.1/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I=
github.com/buildkite/terminal-to-html/v3 v3.7.0/go.mod h1:g0ME1XqbkBSgXR9YmlIHcJIjzaMyWW+HbsG0rPb5puo=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
@@ -611,8 +613,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOmkVoJOpwnS0wfdsJCV9CoD5nJYsHoFk/0CrTK4M=
+16 -5
View File
@@ -6,17 +6,24 @@ import (
"git.ohea.xyz/cursorius/server/config"
"git.ohea.xyz/cursorius/server/jobscheduler"
"git.ohea.xyz/cursorius/server/pipeline_api"
"git.ohea.xyz/cursorius/server/webhook"
"github.com/op/go-logging"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"nhooyr.io/websocket"
)
var log = logging.MustGetLogger("cursorius-server")
func setupHTTPServer(runCh chan jobscheduler.Run, registerCh chan jobscheduler.RunnerRegistration,
jobs map[string]config.Job) {
webhook.CreateWebhookHandler(runCh, jobs)
http.HandleFunc("/runner", func(w http.ResponseWriter, r *http.Request) {
jobs map[string]config.Job) *http.ServeMux {
mux := http.NewServeMux()
webhook.CreateWebhookHandler(runCh, jobs, mux)
pipeline_api.CreateHandler(mux)
mux.HandleFunc("/runner", func(w http.ResponseWriter, r *http.Request) {
conn, err := websocket.Accept(w, r, nil)
if err != nil {
log.Errorf("Could not upgrade runner connection to websocket: %v", err)
@@ -24,14 +31,18 @@ func setupHTTPServer(runCh chan jobscheduler.Run, registerCh chan jobscheduler.R
}
go jobscheduler.RegisterRunner(conn, registerCh)
})
return mux
}
func Listen(address string, port int, runCh chan jobscheduler.Run, registerCh chan jobscheduler.RunnerRegistration, jobs map[string]config.Job) {
setupHTTPServer(runCh, registerCh, jobs)
mux := setupHTTPServer(runCh, registerCh, jobs)
connect_string := fmt.Sprintf("%v:%v", address, port)
log.Noticef("Launching HTTP server on %v\n", connect_string)
log.Fatal(http.ListenAndServe(connect_string, nil))
log.Fatal(http.ListenAndServe(
connect_string,
h2c.NewHandler(mux, &http2.Server{}),
))
}
+33
View File
@@ -0,0 +1,33 @@
package pipeline_api
import (
"context"
"net/http"
get_runnerv1 "git.ohea.xyz/cursorius/server/proto/gen/get_runner/v1"
"git.ohea.xyz/cursorius/server/proto/gen/get_runner/v1/get_runnerv1connect"
"github.com/bufbuild/connect-go"
"github.com/op/go-logging"
)
var log = logging.MustGetLogger("cursorius-server")
type ApiServer struct{}
func (s *ApiServer) GetRunner(
ctx context.Context,
req *connect.Request[get_runnerv1.GetRunnerRequest],
) (*connect.Response[get_runnerv1.GetRunnerResponse], error) {
log.Debugf("Request Headers: %v", req.Header())
res := connect.NewResponse(&get_runnerv1.GetRunnerResponse{
Success: true,
})
res.Header().Set("GetRunner-Version", "v1")
return res, nil
}
func CreateHandler(mux *http.ServeMux) {
api_server := &ApiServer{}
path, handler := get_runnerv1connect.NewGetRunnerServiceHandler(api_server)
mux.Handle(path, handler)
}
+8
View File
@@ -0,0 +1,8 @@
version: v1
plugins:
- name: go
out: gen
opt: paths=source_relative
- name: connect-go
out: gen
opt: paths=source_relative
+7
View File
@@ -0,0 +1,7 @@
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
+218
View File
@@ -0,0 +1,218 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: get_runner/v1/get_runner.proto
package get_runnerv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type GetRunnerRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
}
func (x *GetRunnerRequest) Reset() {
*x = GetRunnerRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_get_runner_v1_get_runner_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetRunnerRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetRunnerRequest) ProtoMessage() {}
func (x *GetRunnerRequest) ProtoReflect() protoreflect.Message {
mi := &file_get_runner_v1_get_runner_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetRunnerRequest.ProtoReflect.Descriptor instead.
func (*GetRunnerRequest) Descriptor() ([]byte, []int) {
return file_get_runner_v1_get_runner_proto_rawDescGZIP(), []int{0}
}
func (x *GetRunnerRequest) GetTag() string {
if x != nil {
return x.Tag
}
return ""
}
type GetRunnerResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
}
func (x *GetRunnerResponse) Reset() {
*x = GetRunnerResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_get_runner_v1_get_runner_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetRunnerResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetRunnerResponse) ProtoMessage() {}
func (x *GetRunnerResponse) ProtoReflect() protoreflect.Message {
mi := &file_get_runner_v1_get_runner_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetRunnerResponse.ProtoReflect.Descriptor instead.
func (*GetRunnerResponse) Descriptor() ([]byte, []int) {
return file_get_runner_v1_get_runner_proto_rawDescGZIP(), []int{1}
}
func (x *GetRunnerResponse) GetSuccess() bool {
if x != nil {
return x.Success
}
return false
}
var File_get_runner_v1_get_runner_proto protoreflect.FileDescriptor
var file_get_runner_v1_get_runner_proto_rawDesc = []byte{
0x0a, 0x1e, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f,
0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x0d, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22,
0x24, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x2d, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6e, 0x6e,
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75,
0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63,
0x63, 0x65, 0x73, 0x73, 0x32, 0x64, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6e, 0x6e, 0x65,
0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x50, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x52,
0x75, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x6e,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e,
0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69,
0x74, 0x2e, 0x6f, 0x68, 0x65, 0x61, 0x2e, 0x78, 0x79, 0x7a, 0x2f, 0x63, 0x75, 0x72, 0x73, 0x6f,
0x72, 0x69, 0x75, 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72,
0x2f, 0x76, 0x31, 0x3b, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x76, 0x31,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_get_runner_v1_get_runner_proto_rawDescOnce sync.Once
file_get_runner_v1_get_runner_proto_rawDescData = file_get_runner_v1_get_runner_proto_rawDesc
)
func file_get_runner_v1_get_runner_proto_rawDescGZIP() []byte {
file_get_runner_v1_get_runner_proto_rawDescOnce.Do(func() {
file_get_runner_v1_get_runner_proto_rawDescData = protoimpl.X.CompressGZIP(file_get_runner_v1_get_runner_proto_rawDescData)
})
return file_get_runner_v1_get_runner_proto_rawDescData
}
var file_get_runner_v1_get_runner_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_get_runner_v1_get_runner_proto_goTypes = []interface{}{
(*GetRunnerRequest)(nil), // 0: get_runner.v1.GetRunnerRequest
(*GetRunnerResponse)(nil), // 1: get_runner.v1.GetRunnerResponse
}
var file_get_runner_v1_get_runner_proto_depIdxs = []int32{
0, // 0: get_runner.v1.GetRunnerService.GetRunner:input_type -> get_runner.v1.GetRunnerRequest
1, // 1: get_runner.v1.GetRunnerService.GetRunner:output_type -> get_runner.v1.GetRunnerResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_get_runner_v1_get_runner_proto_init() }
func file_get_runner_v1_get_runner_proto_init() {
if File_get_runner_v1_get_runner_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_get_runner_v1_get_runner_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetRunnerRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_get_runner_v1_get_runner_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetRunnerResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_get_runner_v1_get_runner_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_get_runner_v1_get_runner_proto_goTypes,
DependencyIndexes: file_get_runner_v1_get_runner_proto_depIdxs,
MessageInfos: file_get_runner_v1_get_runner_proto_msgTypes,
}.Build()
File_get_runner_v1_get_runner_proto = out.File
file_get_runner_v1_get_runner_proto_rawDesc = nil
file_get_runner_v1_get_runner_proto_goTypes = nil
file_get_runner_v1_get_runner_proto_depIdxs = nil
}
@@ -0,0 +1,86 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: get_runner/v1/get_runner.proto
package get_runnerv1connect
import (
context "context"
errors "errors"
v1 "git.ohea.xyz/cursorius/server/proto/gen/get_runner/v1"
connect_go "github.com/bufbuild/connect-go"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// GetRunnerServiceName is the fully-qualified name of the GetRunnerService service.
GetRunnerServiceName = "get_runner.v1.GetRunnerService"
)
// GetRunnerServiceClient is a client for the get_runner.v1.GetRunnerService service.
type GetRunnerServiceClient interface {
GetRunner(context.Context, *connect_go.Request[v1.GetRunnerRequest]) (*connect_go.Response[v1.GetRunnerResponse], error)
}
// NewGetRunnerServiceClient constructs a client for the get_runner.v1.GetRunnerService service. By
// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewGetRunnerServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) GetRunnerServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &getRunnerServiceClient{
getRunner: connect_go.NewClient[v1.GetRunnerRequest, v1.GetRunnerResponse](
httpClient,
baseURL+"/get_runner.v1.GetRunnerService/GetRunner",
opts...,
),
}
}
// getRunnerServiceClient implements GetRunnerServiceClient.
type getRunnerServiceClient struct {
getRunner *connect_go.Client[v1.GetRunnerRequest, v1.GetRunnerResponse]
}
// GetRunner calls get_runner.v1.GetRunnerService.GetRunner.
func (c *getRunnerServiceClient) GetRunner(ctx context.Context, req *connect_go.Request[v1.GetRunnerRequest]) (*connect_go.Response[v1.GetRunnerResponse], error) {
return c.getRunner.CallUnary(ctx, req)
}
// GetRunnerServiceHandler is an implementation of the get_runner.v1.GetRunnerService service.
type GetRunnerServiceHandler interface {
GetRunner(context.Context, *connect_go.Request[v1.GetRunnerRequest]) (*connect_go.Response[v1.GetRunnerResponse], error)
}
// NewGetRunnerServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewGetRunnerServiceHandler(svc GetRunnerServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/get_runner.v1.GetRunnerService/GetRunner", connect_go.NewUnaryHandler(
"/get_runner.v1.GetRunnerService/GetRunner",
svc.GetRunner,
opts...,
))
return "/get_runner.v1.GetRunnerService/", mux
}
// UnimplementedGetRunnerServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedGetRunnerServiceHandler struct{}
func (UnimplementedGetRunnerServiceHandler) GetRunner(context.Context, *connect_go.Request[v1.GetRunnerRequest]) (*connect_go.Response[v1.GetRunnerResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("get_runner.v1.GetRunnerService.GetRunner is not implemented"))
}
+17
View File
@@ -0,0 +1,17 @@
syntax = "proto3";
package get_runner.v1;
option go_package = "git.ohea.xyz/cursorius/server/proto/gen/get_runner/v1;get_runnerv1";
message GetRunnerRequest {
string tag = 1;
}
message GetRunnerResponse {
bool success = 1;
}
service GetRunnerService {
rpc GetRunner(GetRunnerRequest) returns (GetRunnerResponse) {}
}
+2 -2
View File
@@ -12,8 +12,8 @@ import (
var log = logging.MustGetLogger("cursorius-server")
func CreateWebhookHandler(runCh chan jobscheduler.Run, jobs map[string]config.Job) {
http.HandleFunc("/webhook/", func(w http.ResponseWriter, r *http.Request) {
func CreateWebhookHandler(runCh chan jobscheduler.Run, jobs map[string]config.Job, mux *http.ServeMux) {
mux.HandleFunc("/webhook/", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "POST":
splitUrl := strings.Split(r.URL.Path, "/")