diff --git a/doc/index.html b/doc/index.html
index 5f1cbd5d..e64b4a49 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -1980,6 +1980,14 @@
Table of Contents
MUpdateBMCInfoResponse
+
+ MWaitForMachineEventRequest
+
+
+
+ MWaitForMachineEventResponse
+
+
@@ -15621,6 +15629,20 @@
+
+ WaitForMachineEventRequest
+
+
+
+
+
+
+ WaitForMachineEventResponse
+
+
+
+
+
@@ -15642,6 +15664,13 @@
UpdateBMCInfo |
+
+ | WaitForMachineEvent |
+ WaitForMachineEventRequest |
+ WaitForMachineEventResponse stream |
+ WaitForMachineEvent is called by the metal-bmc and is returned with a bmc command to execute. |
+
+
diff --git a/generate/go_client.tpl b/generate/go_client.tpl
index c2ffaec9..3f076aeb 100644
--- a/generate/go_client.tpl
+++ b/generate/go_client.tpl
@@ -2,7 +2,6 @@
package client
import (
- "context"
"sync"
"connectrpc.com/connect"
@@ -53,33 +52,17 @@ func New(config *DialConfig) (Client, error) {
interceptors: []connect.Interceptor{},
}
- authInterceptor := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
- return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
- request.Header().Add("Authorization", "Bearer "+config.Token)
- return next(ctx, request)
- })
- })
-
- loggingInterceptor := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
- return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
- config.Log.Debug("intercept", "request procedure", request.Spec().Procedure, "body", request.Any())
- response, err := next(ctx, request)
- if err != nil {
- return nil, err
- }
- config.Log.Debug("intercept", "request procedure", request.Spec().Procedure, "response", response.Any())
- return response, err
- })
- })
-
if config.Token != "" {
+ authInterceptor := &authInterceptor{config: config}
c.interceptors = append(c.interceptors, authInterceptor)
}
if config.Log != nil {
+ loggingInterceptor := &loggingInterceptor{config: config}
c.interceptors = append(c.interceptors, loggingInterceptor)
}
c.interceptors = append(c.interceptors, config.Interceptors...)
+ // TODO convert to interceptor
go c.startTokenRenewal()
return c, nil
diff --git a/go.mod b/go.mod
index b0c5974f..463acc71 100644
--- a/go.mod
+++ b/go.mod
@@ -7,6 +7,7 @@ require (
buf.build/go/protovalidate v1.1.0
connectrpc.com/connect v1.19.1
github.com/bufbuild/protocompile v0.14.1
+ github.com/davecgh/go-spew v1.1.1
github.com/go-task/slim-sprig/v3 v3.0.0
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/go-cmp v0.7.0
@@ -18,7 +19,6 @@ require (
require (
cel.dev/expr v0.25.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
- github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/cel-go v0.26.1 // indirect
github.com/klauspost/compress v1.18.2 // indirect
github.com/kr/pretty v0.3.1 // indirect
diff --git a/go/client/client-interceptors.go b/go/client/client-interceptors.go
new file mode 100644
index 00000000..0d9c678e
--- /dev/null
+++ b/go/client/client-interceptors.go
@@ -0,0 +1,67 @@
+package client
+
+import (
+ "context"
+
+ "connectrpc.com/connect"
+)
+
+// authinterceptor adds the required auth headers
+type authInterceptor struct {
+ config *DialConfig
+}
+
+func (i *authInterceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc {
+ return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
+ request.Header().Add("Authorization", "Bearer "+i.config.Token)
+ return next(ctx, request)
+ })
+}
+
+func (i *authInterceptor) WrapStreamingClient(next connect.StreamingClientFunc) connect.StreamingClientFunc {
+ return func(ctx context.Context, spec connect.Spec) connect.StreamingClientConn {
+ return &streamingInterceptorConn{
+ StreamingClientConn: next(ctx, spec),
+ token: i.config.Token,
+ }
+ }
+}
+
+func (i *authInterceptor) WrapStreamingHandler(next connect.StreamingHandlerFunc) connect.StreamingHandlerFunc {
+ return next
+}
+
+type streamingInterceptorConn struct {
+ connect.StreamingClientConn
+ token string
+}
+
+func (conn *streamingInterceptorConn) Send(m any) error {
+ conn.RequestHeader().Add("Authorization", "Bearer "+conn.token)
+ return conn.StreamingClientConn.Send(m)
+}
+
+type loggingInterceptor struct {
+ config *DialConfig
+}
+
+func (i *loggingInterceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc {
+ return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
+ i.config.Log.Debug("intercept", "request procedure", request.Spec().Procedure, "body", request.Any())
+ response, err := next(ctx, request)
+ if err != nil {
+ return nil, err
+ }
+ i.config.Log.Debug("intercept", "request procedure", request.Spec().Procedure, "response", response.Any())
+ return response, err
+ })
+}
+
+func (i *loggingInterceptor) WrapStreamingClient(next connect.StreamingClientFunc) connect.StreamingClientFunc {
+ // TODO also log here
+ return next
+}
+
+func (i *loggingInterceptor) WrapStreamingHandler(next connect.StreamingHandlerFunc) connect.StreamingHandlerFunc {
+ return next
+}
diff --git a/go/client/client.go b/go/client/client.go
index ff4d4730..374b5cc2 100755
--- a/go/client/client.go
+++ b/go/client/client.go
@@ -2,7 +2,6 @@
package client
import (
- "context"
"sync"
"connectrpc.com/connect"
@@ -114,33 +113,17 @@ func New(config *DialConfig) (Client, error) {
interceptors: []connect.Interceptor{},
}
- authInterceptor := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
- return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
- request.Header().Add("Authorization", "Bearer "+config.Token)
- return next(ctx, request)
- })
- })
-
- loggingInterceptor := connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
- return connect.UnaryFunc(func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
- config.Log.Debug("intercept", "request procedure", request.Spec().Procedure, "body", request.Any())
- response, err := next(ctx, request)
- if err != nil {
- return nil, err
- }
- config.Log.Debug("intercept", "request procedure", request.Spec().Procedure, "response", response.Any())
- return response, err
- })
- })
-
if config.Token != "" {
+ authInterceptor := &authInterceptor{config: config}
c.interceptors = append(c.interceptors, authInterceptor)
}
if config.Log != nil {
+ loggingInterceptor := &loggingInterceptor{config: config}
c.interceptors = append(c.interceptors, loggingInterceptor)
}
c.interceptors = append(c.interceptors, config.Interceptors...)
+ // TODO convert to interceptor
go c.startTokenRenewal()
return c, nil
diff --git a/go/client/client_test.go b/go/client/client_test.go
index 64cf3fe0..c5b1e3e4 100644
--- a/go/client/client_test.go
+++ b/go/client/client_test.go
@@ -20,6 +20,8 @@ import (
"github.com/metal-stack/api/go/client"
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
"github.com/metal-stack/api/go/metalstack/api/v2/apiv2connect"
+ infrav2 "github.com/metal-stack/api/go/metalstack/infra/v2"
+ "github.com/metal-stack/api/go/metalstack/infra/v2/infrav2connect"
"github.com/stretchr/testify/require"
)
@@ -155,3 +157,74 @@ func (m *mockTokenService) Revoke(context.Context, *apiv2.TokenServiceRevokeRequ
func (m *mockTokenService) Update(context.Context, *apiv2.TokenServiceUpdateRequest) (*apiv2.TokenServiceUpdateResponse, error) {
panic("unimplemented")
}
+
+func Test_ClientInterceptors(t *testing.T) {
+ var (
+ bs = &mockBMCService{}
+ mux = http.NewServeMux()
+ log = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))
+ ctx = t.Context()
+ )
+
+ mux.Handle(infrav2connect.NewBMCServiceHandler(bs))
+ server := httptest.NewTLSServer(mux)
+ server.EnableHTTP2 = true
+ defer func() {
+ server.Close()
+ }()
+
+ tokenString, err := generateToken(1 * time.Second)
+ require.NoError(t, err)
+
+ c, err := client.New(&client.DialConfig{
+ BaseURL: server.URL,
+ Token: tokenString,
+ Transport: server.Client().Transport,
+ Log: log,
+ })
+ require.NoError(t, err)
+
+ // Synchronous call has authheader set
+ resp, err := c.Infrav2().BMC().UpdateBMCInfo(ctx, &infrav2.UpdateBMCInfoRequest{})
+ require.NoError(t, err)
+ require.NotNil(t, resp)
+ require.Equal(t, tokenString, bs.token)
+ bs.token = ""
+
+ // Asynchronous call has authheader set
+ stream, err := c.Infrav2().BMC().WaitForMachineEvent(ctx, &infrav2.WaitForMachineEventRequest{})
+ require.NoError(t, err)
+ require.NotNil(t, stream)
+ require.Equal(t, tokenString, bs.token)
+}
+
+type mockBMCService struct {
+ token string
+}
+
+func (m *mockBMCService) UpdateBMCInfo(ctx context.Context, _ *infrav2.UpdateBMCInfoRequest) (*infrav2.UpdateBMCInfoResponse, error) {
+ callinfo, _ := connect.CallInfoForHandlerContext(ctx)
+ authHeader := callinfo.RequestHeader().Get("Authorization")
+
+ _, token, found := strings.Cut(authHeader, "Bearer ")
+
+ if !found {
+ return nil, fmt.Errorf("unable to extract token from header:%s", authHeader)
+ }
+ m.token = token
+ return &infrav2.UpdateBMCInfoResponse{}, nil
+}
+
+func (m *mockBMCService) WaitForMachineEvent(ctx context.Context, _ *infrav2.WaitForMachineEventRequest, stream *connect.ServerStream[infrav2.WaitForMachineEventResponse]) error {
+ callinfo, _ := connect.CallInfoForHandlerContext(ctx)
+ authHeader := callinfo.RequestHeader().Get("Authorization")
+
+ _, token, found := strings.Cut(authHeader, "Bearer ")
+
+ if !found {
+ return fmt.Errorf("unable to extract token from header:%s", authHeader)
+ }
+
+ m.token = token
+ return stream.Send(&infrav2.WaitForMachineEventResponse{})
+}
diff --git a/go/metalstack/infra/v2/bmc.pb.go b/go/metalstack/infra/v2/bmc.pb.go
index f5457b09..e0836a17 100644
--- a/go/metalstack/infra/v2/bmc.pb.go
+++ b/go/metalstack/infra/v2/bmc.pb.go
@@ -96,16 +96,93 @@ func (*UpdateBMCInfoResponse) Descriptor() ([]byte, []int) {
return file_metalstack_infra_v2_bmc_proto_rawDescGZIP(), []int{1}
}
+// WaitForMachineEventRequest
+type WaitForMachineEventRequest struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *WaitForMachineEventRequest) Reset() {
+ *x = WaitForMachineEventRequest{}
+ mi := &file_metalstack_infra_v2_bmc_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *WaitForMachineEventRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WaitForMachineEventRequest) ProtoMessage() {}
+
+func (x *WaitForMachineEventRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_metalstack_infra_v2_bmc_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use WaitForMachineEventRequest.ProtoReflect.Descriptor instead.
+func (*WaitForMachineEventRequest) Descriptor() ([]byte, []int) {
+ return file_metalstack_infra_v2_bmc_proto_rawDescGZIP(), []int{2}
+}
+
+// WaitForMachineEventResponse
+type WaitForMachineEventResponse struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *WaitForMachineEventResponse) Reset() {
+ *x = WaitForMachineEventResponse{}
+ mi := &file_metalstack_infra_v2_bmc_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *WaitForMachineEventResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WaitForMachineEventResponse) ProtoMessage() {}
+
+func (x *WaitForMachineEventResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_metalstack_infra_v2_bmc_proto_msgTypes[3]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use WaitForMachineEventResponse.ProtoReflect.Descriptor instead.
+func (*WaitForMachineEventResponse) Descriptor() ([]byte, []int) {
+ return file_metalstack_infra_v2_bmc_proto_rawDescGZIP(), []int{3}
+}
+
var File_metalstack_infra_v2_bmc_proto protoreflect.FileDescriptor
const file_metalstack_infra_v2_bmc_proto_rawDesc = "" +
"\n" +
"\x1dmetalstack/infra/v2/bmc.proto\x12\x13metalstack.infra.v2\x1a\x1emetalstack/api/v2/common.proto\"\x16\n" +
"\x14UpdateBMCInfoRequest\"\x17\n" +
- "\x15UpdateBMCInfoResponse2\x7f\n" +
+ "\x15UpdateBMCInfoResponse\"\x1c\n" +
+ "\x1aWaitForMachineEventRequest\"\x1d\n" +
+ "\x1bWaitForMachineEventResponse2\x87\x02\n" +
"\n" +
"BMCService\x12q\n" +
- "\rUpdateBMCInfo\x12).metalstack.infra.v2.UpdateBMCInfoRequest\x1a*.metalstack.infra.v2.UpdateBMCInfoResponse\"\t\xe0\xf3\x18\x02\xea\xf3\x18\x01\x01B\xcc\x01\n" +
+ "\rUpdateBMCInfo\x12).metalstack.infra.v2.UpdateBMCInfoRequest\x1a*.metalstack.infra.v2.UpdateBMCInfoResponse\"\t\xe0\xf3\x18\x02\xea\xf3\x18\x01\x01\x12\x85\x01\n" +
+ "\x13WaitForMachineEvent\x12/.metalstack.infra.v2.WaitForMachineEventRequest\x1a0.metalstack.infra.v2.WaitForMachineEventResponse\"\t\xe0\xf3\x18\x02\xea\xf3\x18\x01\x010\x01B\xcc\x01\n" +
"\x17com.metalstack.infra.v2B\bBmcProtoP\x01Z9github.com/metal-stack/api/go/metalstack/infra/v2;infrav2\xa2\x02\x03MIX\xaa\x02\x13Metalstack.Infra.V2\xca\x02\x13Metalstack\\Infra\\V2\xe2\x02\x1fMetalstack\\Infra\\V2\\GPBMetadata\xea\x02\x15Metalstack::Infra::V2b\x06proto3"
var (
@@ -120,16 +197,20 @@ func file_metalstack_infra_v2_bmc_proto_rawDescGZIP() []byte {
return file_metalstack_infra_v2_bmc_proto_rawDescData
}
-var file_metalstack_infra_v2_bmc_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_metalstack_infra_v2_bmc_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_metalstack_infra_v2_bmc_proto_goTypes = []any{
- (*UpdateBMCInfoRequest)(nil), // 0: metalstack.infra.v2.UpdateBMCInfoRequest
- (*UpdateBMCInfoResponse)(nil), // 1: metalstack.infra.v2.UpdateBMCInfoResponse
+ (*UpdateBMCInfoRequest)(nil), // 0: metalstack.infra.v2.UpdateBMCInfoRequest
+ (*UpdateBMCInfoResponse)(nil), // 1: metalstack.infra.v2.UpdateBMCInfoResponse
+ (*WaitForMachineEventRequest)(nil), // 2: metalstack.infra.v2.WaitForMachineEventRequest
+ (*WaitForMachineEventResponse)(nil), // 3: metalstack.infra.v2.WaitForMachineEventResponse
}
var file_metalstack_infra_v2_bmc_proto_depIdxs = []int32{
0, // 0: metalstack.infra.v2.BMCService.UpdateBMCInfo:input_type -> metalstack.infra.v2.UpdateBMCInfoRequest
- 1, // 1: metalstack.infra.v2.BMCService.UpdateBMCInfo:output_type -> metalstack.infra.v2.UpdateBMCInfoResponse
- 1, // [1:2] is the sub-list for method output_type
- 0, // [0:1] is the sub-list for method input_type
+ 2, // 1: metalstack.infra.v2.BMCService.WaitForMachineEvent:input_type -> metalstack.infra.v2.WaitForMachineEventRequest
+ 1, // 2: metalstack.infra.v2.BMCService.UpdateBMCInfo:output_type -> metalstack.infra.v2.UpdateBMCInfoResponse
+ 3, // 3: metalstack.infra.v2.BMCService.WaitForMachineEvent:output_type -> metalstack.infra.v2.WaitForMachineEventResponse
+ 2, // [2:4] is the sub-list for method output_type
+ 0, // [0:2] 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
@@ -146,7 +227,7 @@ func file_metalstack_infra_v2_bmc_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metalstack_infra_v2_bmc_proto_rawDesc), len(file_metalstack_infra_v2_bmc_proto_rawDesc)),
NumEnums: 0,
- NumMessages: 2,
+ NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/go/metalstack/infra/v2/infrav2connect/bmc.connect.go b/go/metalstack/infra/v2/infrav2connect/bmc.connect.go
index 33234330..d4a2a591 100644
--- a/go/metalstack/infra/v2/infrav2connect/bmc.connect.go
+++ b/go/metalstack/infra/v2/infrav2connect/bmc.connect.go
@@ -36,12 +36,17 @@ const (
// BMCServiceUpdateBMCInfoProcedure is the fully-qualified name of the BMCService's UpdateBMCInfo
// RPC.
BMCServiceUpdateBMCInfoProcedure = "/metalstack.infra.v2.BMCService/UpdateBMCInfo"
+ // BMCServiceWaitForMachineEventProcedure is the fully-qualified name of the BMCService's
+ // WaitForMachineEvent RPC.
+ BMCServiceWaitForMachineEventProcedure = "/metalstack.infra.v2.BMCService/WaitForMachineEvent"
)
// BMCServiceClient is a client for the metalstack.infra.v2.BMCService service.
type BMCServiceClient interface {
// UpdateBMCInfo
UpdateBMCInfo(context.Context, *v2.UpdateBMCInfoRequest) (*v2.UpdateBMCInfoResponse, error)
+ // WaitForMachineEvent is called by the metal-bmc and is returned with a bmc command to execute.
+ WaitForMachineEvent(context.Context, *v2.WaitForMachineEventRequest) (*connect.ServerStreamForClient[v2.WaitForMachineEventResponse], error)
}
// NewBMCServiceClient constructs a client for the metalstack.infra.v2.BMCService service. By
@@ -61,12 +66,19 @@ func NewBMCServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...
connect.WithSchema(bMCServiceMethods.ByName("UpdateBMCInfo")),
connect.WithClientOptions(opts...),
),
+ waitForMachineEvent: connect.NewClient[v2.WaitForMachineEventRequest, v2.WaitForMachineEventResponse](
+ httpClient,
+ baseURL+BMCServiceWaitForMachineEventProcedure,
+ connect.WithSchema(bMCServiceMethods.ByName("WaitForMachineEvent")),
+ connect.WithClientOptions(opts...),
+ ),
}
}
// bMCServiceClient implements BMCServiceClient.
type bMCServiceClient struct {
- updateBMCInfo *connect.Client[v2.UpdateBMCInfoRequest, v2.UpdateBMCInfoResponse]
+ updateBMCInfo *connect.Client[v2.UpdateBMCInfoRequest, v2.UpdateBMCInfoResponse]
+ waitForMachineEvent *connect.Client[v2.WaitForMachineEventRequest, v2.WaitForMachineEventResponse]
}
// UpdateBMCInfo calls metalstack.infra.v2.BMCService.UpdateBMCInfo.
@@ -78,10 +90,17 @@ func (c *bMCServiceClient) UpdateBMCInfo(ctx context.Context, req *v2.UpdateBMCI
return nil, err
}
+// WaitForMachineEvent calls metalstack.infra.v2.BMCService.WaitForMachineEvent.
+func (c *bMCServiceClient) WaitForMachineEvent(ctx context.Context, req *v2.WaitForMachineEventRequest) (*connect.ServerStreamForClient[v2.WaitForMachineEventResponse], error) {
+ return c.waitForMachineEvent.CallServerStream(ctx, connect.NewRequest(req))
+}
+
// BMCServiceHandler is an implementation of the metalstack.infra.v2.BMCService service.
type BMCServiceHandler interface {
// UpdateBMCInfo
UpdateBMCInfo(context.Context, *v2.UpdateBMCInfoRequest) (*v2.UpdateBMCInfoResponse, error)
+ // WaitForMachineEvent is called by the metal-bmc and is returned with a bmc command to execute.
+ WaitForMachineEvent(context.Context, *v2.WaitForMachineEventRequest, *connect.ServerStream[v2.WaitForMachineEventResponse]) error
}
// NewBMCServiceHandler builds an HTTP handler from the service implementation. It returns the path
@@ -97,10 +116,18 @@ func NewBMCServiceHandler(svc BMCServiceHandler, opts ...connect.HandlerOption)
connect.WithSchema(bMCServiceMethods.ByName("UpdateBMCInfo")),
connect.WithHandlerOptions(opts...),
)
+ bMCServiceWaitForMachineEventHandler := connect.NewServerStreamHandlerSimple(
+ BMCServiceWaitForMachineEventProcedure,
+ svc.WaitForMachineEvent,
+ connect.WithSchema(bMCServiceMethods.ByName("WaitForMachineEvent")),
+ connect.WithHandlerOptions(opts...),
+ )
return "/metalstack.infra.v2.BMCService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case BMCServiceUpdateBMCInfoProcedure:
bMCServiceUpdateBMCInfoHandler.ServeHTTP(w, r)
+ case BMCServiceWaitForMachineEventProcedure:
+ bMCServiceWaitForMachineEventHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
@@ -113,3 +140,7 @@ type UnimplementedBMCServiceHandler struct{}
func (UnimplementedBMCServiceHandler) UpdateBMCInfo(context.Context, *v2.UpdateBMCInfoRequest) (*v2.UpdateBMCInfoResponse, error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("metalstack.infra.v2.BMCService.UpdateBMCInfo is not implemented"))
}
+
+func (UnimplementedBMCServiceHandler) WaitForMachineEvent(context.Context, *v2.WaitForMachineEventRequest, *connect.ServerStream[v2.WaitForMachineEventResponse]) error {
+ return connect.NewError(connect.CodeUnimplemented, errors.New("metalstack.infra.v2.BMCService.WaitForMachineEvent is not implemented"))
+}
diff --git a/go/permissions/servicepermissions.go b/go/permissions/servicepermissions.go
index d98d2474..e0bffa0b 100755
--- a/go/permissions/servicepermissions.go
+++ b/go/permissions/servicepermissions.go
@@ -100,6 +100,7 @@ func GetServicePermissions() *ServicePermissions {
Infra: Infra{
"INFRA_ROLE_EDITOR": []string{
"/metalstack.infra.v2.BMCService/UpdateBMCInfo",
+ "/metalstack.infra.v2.BMCService/WaitForMachineEvent",
"/metalstack.infra.v2.EventService/Send",
"/metalstack.infra.v2.SwitchService/Get",
"/metalstack.infra.v2.SwitchService/Register",
@@ -298,6 +299,7 @@ func GetServicePermissions() *ServicePermissions {
"/metalstack.api.v2.UserService/Get": true,
"/metalstack.api.v2.VersionService/Get": true,
"/metalstack.infra.v2.BMCService/UpdateBMCInfo": true,
+ "/metalstack.infra.v2.BMCService/WaitForMachineEvent": true,
"/metalstack.infra.v2.EventService/Send": true,
"/metalstack.infra.v2.SwitchService/Get": true,
"/metalstack.infra.v2.SwitchService/Heartbeat": true,
@@ -377,11 +379,12 @@ func GetServicePermissions() *ServicePermissions {
"/metalstack.admin.v2.VPNService/ListNodes": true,
},
Infra: map[string]bool{
- "/metalstack.infra.v2.BMCService/UpdateBMCInfo": true,
- "/metalstack.infra.v2.EventService/Send": true,
- "/metalstack.infra.v2.SwitchService/Get": true,
- "/metalstack.infra.v2.SwitchService/Heartbeat": true,
- "/metalstack.infra.v2.SwitchService/Register": true,
+ "/metalstack.infra.v2.BMCService/UpdateBMCInfo": true,
+ "/metalstack.infra.v2.BMCService/WaitForMachineEvent": true,
+ "/metalstack.infra.v2.EventService/Send": true,
+ "/metalstack.infra.v2.SwitchService/Get": true,
+ "/metalstack.infra.v2.SwitchService/Heartbeat": true,
+ "/metalstack.infra.v2.SwitchService/Register": true,
},
Tenant: map[string]bool{
"/metalstack.api.v2.ProjectService/Create": true,
@@ -424,110 +427,111 @@ func GetServicePermissions() *ServicePermissions {
},
},
Auditable: map[string]bool{
- "/metalstack.admin.v2.FilesystemService/Create": true,
- "/metalstack.admin.v2.FilesystemService/Delete": true,
- "/metalstack.admin.v2.FilesystemService/Update": true,
- "/metalstack.admin.v2.IPService/List": false,
- "/metalstack.admin.v2.ImageService/Create": true,
- "/metalstack.admin.v2.ImageService/Delete": true,
- "/metalstack.admin.v2.ImageService/Update": true,
- "/metalstack.admin.v2.ImageService/Usage": true,
- "/metalstack.admin.v2.MachineService/Get": false,
- "/metalstack.admin.v2.MachineService/List": false,
- "/metalstack.admin.v2.NetworkService/Create": true,
- "/metalstack.admin.v2.NetworkService/Delete": true,
- "/metalstack.admin.v2.NetworkService/Get": false,
- "/metalstack.admin.v2.NetworkService/List": false,
- "/metalstack.admin.v2.NetworkService/Update": true,
- "/metalstack.admin.v2.PartitionService/Capacity": false,
- "/metalstack.admin.v2.PartitionService/Create": true,
- "/metalstack.admin.v2.PartitionService/Delete": true,
- "/metalstack.admin.v2.PartitionService/Update": true,
- "/metalstack.admin.v2.ProjectService/List": false,
- "/metalstack.admin.v2.SizeService/Create": true,
- "/metalstack.admin.v2.SizeService/Delete": true,
- "/metalstack.admin.v2.SizeService/Update": true,
- "/metalstack.admin.v2.SwitchService/Delete": true,
- "/metalstack.admin.v2.SwitchService/Get": false,
- "/metalstack.admin.v2.SwitchService/List": false,
- "/metalstack.admin.v2.SwitchService/Migrate": true,
- "/metalstack.admin.v2.SwitchService/Port": true,
- "/metalstack.admin.v2.SwitchService/Update": true,
- "/metalstack.admin.v2.TenantService/Create": true,
- "/metalstack.admin.v2.TenantService/List": true,
- "/metalstack.admin.v2.TokenService/Create": true,
- "/metalstack.admin.v2.TokenService/List": true,
- "/metalstack.admin.v2.TokenService/Revoke": true,
- "/metalstack.admin.v2.VPNService/AuthKey": true,
- "/metalstack.admin.v2.VPNService/ListNodes": true,
- "/metalstack.api.v2.FilesystemService/Get": false,
- "/metalstack.api.v2.FilesystemService/List": false,
- "/metalstack.api.v2.FilesystemService/Match": false,
- "/metalstack.api.v2.HealthService/Get": false,
- "/metalstack.api.v2.IPService/Create": true,
- "/metalstack.api.v2.IPService/Delete": true,
- "/metalstack.api.v2.IPService/Get": false,
- "/metalstack.api.v2.IPService/List": false,
- "/metalstack.api.v2.IPService/Update": true,
- "/metalstack.api.v2.ImageService/Get": false,
- "/metalstack.api.v2.ImageService/Latest": false,
- "/metalstack.api.v2.ImageService/List": false,
- "/metalstack.api.v2.MachineService/Create": true,
- "/metalstack.api.v2.MachineService/Delete": true,
- "/metalstack.api.v2.MachineService/Get": false,
- "/metalstack.api.v2.MachineService/List": false,
- "/metalstack.api.v2.MachineService/Update": true,
- "/metalstack.api.v2.MethodService/List": true,
- "/metalstack.api.v2.MethodService/TokenScopedList": true,
- "/metalstack.api.v2.NetworkService/Create": true,
- "/metalstack.api.v2.NetworkService/Delete": true,
- "/metalstack.api.v2.NetworkService/Get": false,
- "/metalstack.api.v2.NetworkService/List": false,
- "/metalstack.api.v2.NetworkService/ListBaseNetworks": false,
- "/metalstack.api.v2.NetworkService/Update": true,
- "/metalstack.api.v2.PartitionService/Get": false,
- "/metalstack.api.v2.PartitionService/List": false,
- "/metalstack.api.v2.ProjectService/Create": true,
- "/metalstack.api.v2.ProjectService/Delete": true,
- "/metalstack.api.v2.ProjectService/Get": false,
- "/metalstack.api.v2.ProjectService/Invite": true,
- "/metalstack.api.v2.ProjectService/InviteAccept": true,
- "/metalstack.api.v2.ProjectService/InviteDelete": true,
- "/metalstack.api.v2.ProjectService/InviteGet": false,
- "/metalstack.api.v2.ProjectService/InvitesList": false,
- "/metalstack.api.v2.ProjectService/Leave": true,
- "/metalstack.api.v2.ProjectService/List": false,
- "/metalstack.api.v2.ProjectService/RemoveMember": true,
- "/metalstack.api.v2.ProjectService/Update": true,
- "/metalstack.api.v2.ProjectService/UpdateMember": true,
- "/metalstack.api.v2.SizeService/Get": false,
- "/metalstack.api.v2.SizeService/List": false,
- "/metalstack.api.v2.TenantService/Create": true,
- "/metalstack.api.v2.TenantService/Delete": true,
- "/metalstack.api.v2.TenantService/Get": false,
- "/metalstack.api.v2.TenantService/Invite": true,
- "/metalstack.api.v2.TenantService/InviteAccept": true,
- "/metalstack.api.v2.TenantService/InviteDelete": true,
- "/metalstack.api.v2.TenantService/InviteGet": false,
- "/metalstack.api.v2.TenantService/InvitesList": false,
- "/metalstack.api.v2.TenantService/Leave": true,
- "/metalstack.api.v2.TenantService/List": false,
- "/metalstack.api.v2.TenantService/RemoveMember": true,
- "/metalstack.api.v2.TenantService/Update": true,
- "/metalstack.api.v2.TenantService/UpdateMember": true,
- "/metalstack.api.v2.TokenService/Create": true,
- "/metalstack.api.v2.TokenService/Get": true,
- "/metalstack.api.v2.TokenService/List": true,
- "/metalstack.api.v2.TokenService/Refresh": true,
- "/metalstack.api.v2.TokenService/Revoke": true,
- "/metalstack.api.v2.TokenService/Update": true,
- "/metalstack.api.v2.UserService/Get": true,
- "/metalstack.api.v2.VersionService/Get": false,
- "/metalstack.infra.v2.BMCService/UpdateBMCInfo": false,
- "/metalstack.infra.v2.EventService/Send": false,
- "/metalstack.infra.v2.SwitchService/Get": false,
- "/metalstack.infra.v2.SwitchService/Heartbeat": false,
- "/metalstack.infra.v2.SwitchService/Register": false,
+ "/metalstack.admin.v2.FilesystemService/Create": true,
+ "/metalstack.admin.v2.FilesystemService/Delete": true,
+ "/metalstack.admin.v2.FilesystemService/Update": true,
+ "/metalstack.admin.v2.IPService/List": false,
+ "/metalstack.admin.v2.ImageService/Create": true,
+ "/metalstack.admin.v2.ImageService/Delete": true,
+ "/metalstack.admin.v2.ImageService/Update": true,
+ "/metalstack.admin.v2.ImageService/Usage": true,
+ "/metalstack.admin.v2.MachineService/Get": false,
+ "/metalstack.admin.v2.MachineService/List": false,
+ "/metalstack.admin.v2.NetworkService/Create": true,
+ "/metalstack.admin.v2.NetworkService/Delete": true,
+ "/metalstack.admin.v2.NetworkService/Get": false,
+ "/metalstack.admin.v2.NetworkService/List": false,
+ "/metalstack.admin.v2.NetworkService/Update": true,
+ "/metalstack.admin.v2.PartitionService/Capacity": false,
+ "/metalstack.admin.v2.PartitionService/Create": true,
+ "/metalstack.admin.v2.PartitionService/Delete": true,
+ "/metalstack.admin.v2.PartitionService/Update": true,
+ "/metalstack.admin.v2.ProjectService/List": false,
+ "/metalstack.admin.v2.SizeService/Create": true,
+ "/metalstack.admin.v2.SizeService/Delete": true,
+ "/metalstack.admin.v2.SizeService/Update": true,
+ "/metalstack.admin.v2.SwitchService/Delete": true,
+ "/metalstack.admin.v2.SwitchService/Get": false,
+ "/metalstack.admin.v2.SwitchService/List": false,
+ "/metalstack.admin.v2.SwitchService/Migrate": true,
+ "/metalstack.admin.v2.SwitchService/Port": true,
+ "/metalstack.admin.v2.SwitchService/Update": true,
+ "/metalstack.admin.v2.TenantService/Create": true,
+ "/metalstack.admin.v2.TenantService/List": true,
+ "/metalstack.admin.v2.TokenService/Create": true,
+ "/metalstack.admin.v2.TokenService/List": true,
+ "/metalstack.admin.v2.TokenService/Revoke": true,
+ "/metalstack.admin.v2.VPNService/AuthKey": true,
+ "/metalstack.admin.v2.VPNService/ListNodes": true,
+ "/metalstack.api.v2.FilesystemService/Get": false,
+ "/metalstack.api.v2.FilesystemService/List": false,
+ "/metalstack.api.v2.FilesystemService/Match": false,
+ "/metalstack.api.v2.HealthService/Get": false,
+ "/metalstack.api.v2.IPService/Create": true,
+ "/metalstack.api.v2.IPService/Delete": true,
+ "/metalstack.api.v2.IPService/Get": false,
+ "/metalstack.api.v2.IPService/List": false,
+ "/metalstack.api.v2.IPService/Update": true,
+ "/metalstack.api.v2.ImageService/Get": false,
+ "/metalstack.api.v2.ImageService/Latest": false,
+ "/metalstack.api.v2.ImageService/List": false,
+ "/metalstack.api.v2.MachineService/Create": true,
+ "/metalstack.api.v2.MachineService/Delete": true,
+ "/metalstack.api.v2.MachineService/Get": false,
+ "/metalstack.api.v2.MachineService/List": false,
+ "/metalstack.api.v2.MachineService/Update": true,
+ "/metalstack.api.v2.MethodService/List": true,
+ "/metalstack.api.v2.MethodService/TokenScopedList": true,
+ "/metalstack.api.v2.NetworkService/Create": true,
+ "/metalstack.api.v2.NetworkService/Delete": true,
+ "/metalstack.api.v2.NetworkService/Get": false,
+ "/metalstack.api.v2.NetworkService/List": false,
+ "/metalstack.api.v2.NetworkService/ListBaseNetworks": false,
+ "/metalstack.api.v2.NetworkService/Update": true,
+ "/metalstack.api.v2.PartitionService/Get": false,
+ "/metalstack.api.v2.PartitionService/List": false,
+ "/metalstack.api.v2.ProjectService/Create": true,
+ "/metalstack.api.v2.ProjectService/Delete": true,
+ "/metalstack.api.v2.ProjectService/Get": false,
+ "/metalstack.api.v2.ProjectService/Invite": true,
+ "/metalstack.api.v2.ProjectService/InviteAccept": true,
+ "/metalstack.api.v2.ProjectService/InviteDelete": true,
+ "/metalstack.api.v2.ProjectService/InviteGet": false,
+ "/metalstack.api.v2.ProjectService/InvitesList": false,
+ "/metalstack.api.v2.ProjectService/Leave": true,
+ "/metalstack.api.v2.ProjectService/List": false,
+ "/metalstack.api.v2.ProjectService/RemoveMember": true,
+ "/metalstack.api.v2.ProjectService/Update": true,
+ "/metalstack.api.v2.ProjectService/UpdateMember": true,
+ "/metalstack.api.v2.SizeService/Get": false,
+ "/metalstack.api.v2.SizeService/List": false,
+ "/metalstack.api.v2.TenantService/Create": true,
+ "/metalstack.api.v2.TenantService/Delete": true,
+ "/metalstack.api.v2.TenantService/Get": false,
+ "/metalstack.api.v2.TenantService/Invite": true,
+ "/metalstack.api.v2.TenantService/InviteAccept": true,
+ "/metalstack.api.v2.TenantService/InviteDelete": true,
+ "/metalstack.api.v2.TenantService/InviteGet": false,
+ "/metalstack.api.v2.TenantService/InvitesList": false,
+ "/metalstack.api.v2.TenantService/Leave": true,
+ "/metalstack.api.v2.TenantService/List": false,
+ "/metalstack.api.v2.TenantService/RemoveMember": true,
+ "/metalstack.api.v2.TenantService/Update": true,
+ "/metalstack.api.v2.TenantService/UpdateMember": true,
+ "/metalstack.api.v2.TokenService/Create": true,
+ "/metalstack.api.v2.TokenService/Get": true,
+ "/metalstack.api.v2.TokenService/List": true,
+ "/metalstack.api.v2.TokenService/Refresh": true,
+ "/metalstack.api.v2.TokenService/Revoke": true,
+ "/metalstack.api.v2.TokenService/Update": true,
+ "/metalstack.api.v2.UserService/Get": true,
+ "/metalstack.api.v2.VersionService/Get": false,
+ "/metalstack.infra.v2.BMCService/UpdateBMCInfo": false,
+ "/metalstack.infra.v2.BMCService/WaitForMachineEvent": false,
+ "/metalstack.infra.v2.EventService/Send": false,
+ "/metalstack.infra.v2.SwitchService/Get": false,
+ "/metalstack.infra.v2.SwitchService/Heartbeat": false,
+ "/metalstack.infra.v2.SwitchService/Register": false,
},
}
}
diff --git a/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceClient.go b/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceClient.go
index da746095..9ce708b0 100644
--- a/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceClient.go
+++ b/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceClient.go
@@ -7,6 +7,7 @@ package infrav2connect
import (
"context"
+ "connectrpc.com/connect"
"github.com/metal-stack/api/go/metalstack/infra/v2"
mock "github.com/stretchr/testify/mock"
)
@@ -105,3 +106,71 @@ func (_c *BMCServiceClient_UpdateBMCInfo_Call) RunAndReturn(run func(context1 co
_c.Call.Return(run)
return _c
}
+
+// WaitForMachineEvent provides a mock function for the type BMCServiceClient
+func (_mock *BMCServiceClient) WaitForMachineEvent(context1 context.Context, waitForMachineEventRequest *infrav2.WaitForMachineEventRequest) (*connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse], error) {
+ ret := _mock.Called(context1, waitForMachineEventRequest)
+
+ if len(ret) == 0 {
+ panic("no return value specified for WaitForMachineEvent")
+ }
+
+ var r0 *connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse]
+ var r1 error
+ if returnFunc, ok := ret.Get(0).(func(context.Context, *infrav2.WaitForMachineEventRequest) (*connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse], error)); ok {
+ return returnFunc(context1, waitForMachineEventRequest)
+ }
+ if returnFunc, ok := ret.Get(0).(func(context.Context, *infrav2.WaitForMachineEventRequest) *connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse]); ok {
+ r0 = returnFunc(context1, waitForMachineEventRequest)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse])
+ }
+ }
+ if returnFunc, ok := ret.Get(1).(func(context.Context, *infrav2.WaitForMachineEventRequest) error); ok {
+ r1 = returnFunc(context1, waitForMachineEventRequest)
+ } else {
+ r1 = ret.Error(1)
+ }
+ return r0, r1
+}
+
+// BMCServiceClient_WaitForMachineEvent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WaitForMachineEvent'
+type BMCServiceClient_WaitForMachineEvent_Call struct {
+ *mock.Call
+}
+
+// WaitForMachineEvent is a helper method to define mock.On call
+// - context1 context.Context
+// - waitForMachineEventRequest *infrav2.WaitForMachineEventRequest
+func (_e *BMCServiceClient_Expecter) WaitForMachineEvent(context1 interface{}, waitForMachineEventRequest interface{}) *BMCServiceClient_WaitForMachineEvent_Call {
+ return &BMCServiceClient_WaitForMachineEvent_Call{Call: _e.mock.On("WaitForMachineEvent", context1, waitForMachineEventRequest)}
+}
+
+func (_c *BMCServiceClient_WaitForMachineEvent_Call) Run(run func(context1 context.Context, waitForMachineEventRequest *infrav2.WaitForMachineEventRequest)) *BMCServiceClient_WaitForMachineEvent_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ var arg0 context.Context
+ if args[0] != nil {
+ arg0 = args[0].(context.Context)
+ }
+ var arg1 *infrav2.WaitForMachineEventRequest
+ if args[1] != nil {
+ arg1 = args[1].(*infrav2.WaitForMachineEventRequest)
+ }
+ run(
+ arg0,
+ arg1,
+ )
+ })
+ return _c
+}
+
+func (_c *BMCServiceClient_WaitForMachineEvent_Call) Return(serverStreamForClient *connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse], err error) *BMCServiceClient_WaitForMachineEvent_Call {
+ _c.Call.Return(serverStreamForClient, err)
+ return _c
+}
+
+func (_c *BMCServiceClient_WaitForMachineEvent_Call) RunAndReturn(run func(context1 context.Context, waitForMachineEventRequest *infrav2.WaitForMachineEventRequest) (*connect.ServerStreamForClient[infrav2.WaitForMachineEventResponse], error)) *BMCServiceClient_WaitForMachineEvent_Call {
+ _c.Call.Return(run)
+ return _c
+}
diff --git a/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceHandler.go b/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceHandler.go
index 6442a23d..f566efd2 100644
--- a/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceHandler.go
+++ b/go/tests/mocks/metalstack/infra/v2/infrav2connect/BMCServiceHandler.go
@@ -7,6 +7,7 @@ package infrav2connect
import (
"context"
+ "connectrpc.com/connect"
"github.com/metal-stack/api/go/metalstack/infra/v2"
mock "github.com/stretchr/testify/mock"
)
@@ -105,3 +106,66 @@ func (_c *BMCServiceHandler_UpdateBMCInfo_Call) RunAndReturn(run func(context1 c
_c.Call.Return(run)
return _c
}
+
+// WaitForMachineEvent provides a mock function for the type BMCServiceHandler
+func (_mock *BMCServiceHandler) WaitForMachineEvent(context1 context.Context, waitForMachineEventRequest *infrav2.WaitForMachineEventRequest, serverStream *connect.ServerStream[infrav2.WaitForMachineEventResponse]) error {
+ ret := _mock.Called(context1, waitForMachineEventRequest, serverStream)
+
+ if len(ret) == 0 {
+ panic("no return value specified for WaitForMachineEvent")
+ }
+
+ var r0 error
+ if returnFunc, ok := ret.Get(0).(func(context.Context, *infrav2.WaitForMachineEventRequest, *connect.ServerStream[infrav2.WaitForMachineEventResponse]) error); ok {
+ r0 = returnFunc(context1, waitForMachineEventRequest, serverStream)
+ } else {
+ r0 = ret.Error(0)
+ }
+ return r0
+}
+
+// BMCServiceHandler_WaitForMachineEvent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WaitForMachineEvent'
+type BMCServiceHandler_WaitForMachineEvent_Call struct {
+ *mock.Call
+}
+
+// WaitForMachineEvent is a helper method to define mock.On call
+// - context1 context.Context
+// - waitForMachineEventRequest *infrav2.WaitForMachineEventRequest
+// - serverStream *connect.ServerStream[infrav2.WaitForMachineEventResponse]
+func (_e *BMCServiceHandler_Expecter) WaitForMachineEvent(context1 interface{}, waitForMachineEventRequest interface{}, serverStream interface{}) *BMCServiceHandler_WaitForMachineEvent_Call {
+ return &BMCServiceHandler_WaitForMachineEvent_Call{Call: _e.mock.On("WaitForMachineEvent", context1, waitForMachineEventRequest, serverStream)}
+}
+
+func (_c *BMCServiceHandler_WaitForMachineEvent_Call) Run(run func(context1 context.Context, waitForMachineEventRequest *infrav2.WaitForMachineEventRequest, serverStream *connect.ServerStream[infrav2.WaitForMachineEventResponse])) *BMCServiceHandler_WaitForMachineEvent_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ var arg0 context.Context
+ if args[0] != nil {
+ arg0 = args[0].(context.Context)
+ }
+ var arg1 *infrav2.WaitForMachineEventRequest
+ if args[1] != nil {
+ arg1 = args[1].(*infrav2.WaitForMachineEventRequest)
+ }
+ var arg2 *connect.ServerStream[infrav2.WaitForMachineEventResponse]
+ if args[2] != nil {
+ arg2 = args[2].(*connect.ServerStream[infrav2.WaitForMachineEventResponse])
+ }
+ run(
+ arg0,
+ arg1,
+ arg2,
+ )
+ })
+ return _c
+}
+
+func (_c *BMCServiceHandler_WaitForMachineEvent_Call) Return(err error) *BMCServiceHandler_WaitForMachineEvent_Call {
+ _c.Call.Return(err)
+ return _c
+}
+
+func (_c *BMCServiceHandler_WaitForMachineEvent_Call) RunAndReturn(run func(context1 context.Context, waitForMachineEventRequest *infrav2.WaitForMachineEventRequest, serverStream *connect.ServerStream[infrav2.WaitForMachineEventResponse]) error) *BMCServiceHandler_WaitForMachineEvent_Call {
+ _c.Call.Return(run)
+ return _c
+}
diff --git a/proto/metalstack/infra/v2/bmc.proto b/proto/metalstack/infra/v2/bmc.proto
index 06de6530..fd229b55 100644
--- a/proto/metalstack/infra/v2/bmc.proto
+++ b/proto/metalstack/infra/v2/bmc.proto
@@ -11,6 +11,11 @@ service BMCService {
option (metalstack.api.v2.infra_roles) = INFRA_ROLE_EDITOR;
option (metalstack.api.v2.auditing) = AUDITING_EXCLUDED;
}
+ // WaitForMachineEvent is called by the metal-bmc and is returned with a bmc command to execute.
+ rpc WaitForMachineEvent(WaitForMachineEventRequest) returns (stream WaitForMachineEventResponse) {
+ option (metalstack.api.v2.infra_roles) = INFRA_ROLE_EDITOR;
+ option (metalstack.api.v2.auditing) = AUDITING_EXCLUDED;
+ }
}
// UpdateBMCInfoRequest
@@ -18,3 +23,9 @@ message UpdateBMCInfoRequest {}
// UpdateBMCInfoResponse
message UpdateBMCInfoResponse {}
+
+// WaitForMachineEventRequest
+message WaitForMachineEventRequest {}
+
+// WaitForMachineEventResponse
+message WaitForMachineEventResponse {}
diff --git a/python/metalstack/infra/v2/bmc_connect.py b/python/metalstack/infra/v2/bmc_connect.py
index 1afc8521..bf9951a0 100644
--- a/python/metalstack/infra/v2/bmc_connect.py
+++ b/python/metalstack/infra/v2/bmc_connect.py
@@ -19,6 +19,9 @@ class BMCService(Protocol):
async def update_b_m_c_info(self, request: metalstack_dot_infra_dot_v2_dot_bmc__pb2.UpdateBMCInfoRequest, ctx: RequestContext) -> metalstack_dot_infra_dot_v2_dot_bmc__pb2.UpdateBMCInfoResponse:
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
+ def wait_for_machine_event(self, request: metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest, ctx: RequestContext) -> AsyncIterator[metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse]:
+ raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
+
class BMCServiceASGIApplication(ConnectASGIApplication):
def __init__(self, service: BMCService, *, interceptors: Iterable[Interceptor]=(), read_max_bytes: int | None = None) -> None:
@@ -34,6 +37,16 @@ def __init__(self, service: BMCService, *, interceptors: Iterable[Interceptor]=(
),
function=service.update_b_m_c_info,
),
+ "/metalstack.infra.v2.BMCService/WaitForMachineEvent": Endpoint.server_stream(
+ method=MethodInfo(
+ name="WaitForMachineEvent",
+ service_name="metalstack.infra.v2.BMCService",
+ input=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest,
+ output=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ function=service.wait_for_machine_event,
+ ),
},
interceptors=interceptors,
read_max_bytes=read_max_bytes,
@@ -66,10 +79,32 @@ async def update_b_m_c_info(
timeout_ms=timeout_ms,
)
+ def wait_for_machine_event(
+ self,
+ request: metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest,
+ *,
+ headers: Headers | Mapping[str, str] | None = None,
+ timeout_ms: int | None = None,
+ ) -> AsyncIterator[metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse]:
+ return self.execute_server_stream(
+ request=request,
+ method=MethodInfo(
+ name="WaitForMachineEvent",
+ service_name="metalstack.infra.v2.BMCService",
+ input=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest,
+ output=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ headers=headers,
+ timeout_ms=timeout_ms,
+ )
+
class BMCServiceSync(Protocol):
def update_b_m_c_info(self, request: metalstack_dot_infra_dot_v2_dot_bmc__pb2.UpdateBMCInfoRequest, ctx: RequestContext) -> metalstack_dot_infra_dot_v2_dot_bmc__pb2.UpdateBMCInfoResponse:
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
+ def wait_for_machine_event(self, request: metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest, ctx: RequestContext) -> Iterator[metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse]:
+ raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
class BMCServiceWSGIApplication(ConnectWSGIApplication):
@@ -86,6 +121,16 @@ def __init__(self, service: BMCServiceSync, interceptors: Iterable[InterceptorSy
),
function=service.update_b_m_c_info,
),
+ "/metalstack.infra.v2.BMCService/WaitForMachineEvent": EndpointSync.server_stream(
+ method=MethodInfo(
+ name="WaitForMachineEvent",
+ service_name="metalstack.infra.v2.BMCService",
+ input=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest,
+ output=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ function=service.wait_for_machine_event,
+ ),
},
interceptors=interceptors,
read_max_bytes=read_max_bytes,
@@ -117,3 +162,23 @@ def update_b_m_c_info(
headers=headers,
timeout_ms=timeout_ms,
)
+
+ def wait_for_machine_event(
+ self,
+ request: metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest,
+ *,
+ headers: Headers | Mapping[str, str] | None = None,
+ timeout_ms: int | None = None,
+ ) -> Iterator[metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse]:
+ return self.execute_server_stream(
+ request=request,
+ method=MethodInfo(
+ name="WaitForMachineEvent",
+ service_name="metalstack.infra.v2.BMCService",
+ input=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventRequest,
+ output=metalstack_dot_infra_dot_v2_dot_bmc__pb2.WaitForMachineEventResponse,
+ idempotency_level=IdempotencyLevel.UNKNOWN,
+ ),
+ headers=headers,
+ timeout_ms=timeout_ms,
+ )
diff --git a/python/metalstack/infra/v2/bmc_pb2.py b/python/metalstack/infra/v2/bmc_pb2.py
index 6a849b24..fb5c4d19 100644
--- a/python/metalstack/infra/v2/bmc_pb2.py
+++ b/python/metalstack/infra/v2/bmc_pb2.py
@@ -25,7 +25,7 @@
from metalstack.api.v2 import common_pb2 as metalstack_dot_api_dot_v2_dot_common__pb2
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dmetalstack/infra/v2/bmc.proto\x12\x13metalstack.infra.v2\x1a\x1emetalstack/api/v2/common.proto\"\x16\n\x14UpdateBMCInfoRequest\"\x17\n\x15UpdateBMCInfoResponse2\x7f\n\nBMCService\x12q\n\rUpdateBMCInfo\x12).metalstack.infra.v2.UpdateBMCInfoRequest\x1a*.metalstack.infra.v2.UpdateBMCInfoResponse\"\t\xe0\xf3\x18\x02\xea\xf3\x18\x01\x01\x42\xcc\x01\n\x17\x63om.metalstack.infra.v2B\x08\x42mcProtoP\x01Z9github.com/metal-stack/api/go/metalstack/infra/v2;infrav2\xa2\x02\x03MIX\xaa\x02\x13Metalstack.Infra.V2\xca\x02\x13Metalstack\\Infra\\V2\xe2\x02\x1fMetalstack\\Infra\\V2\\GPBMetadata\xea\x02\x15Metalstack::Infra::V2b\x06proto3')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dmetalstack/infra/v2/bmc.proto\x12\x13metalstack.infra.v2\x1a\x1emetalstack/api/v2/common.proto\"\x16\n\x14UpdateBMCInfoRequest\"\x17\n\x15UpdateBMCInfoResponse\"\x1c\n\x1aWaitForMachineEventRequest\"\x1d\n\x1bWaitForMachineEventResponse2\x87\x02\n\nBMCService\x12q\n\rUpdateBMCInfo\x12).metalstack.infra.v2.UpdateBMCInfoRequest\x1a*.metalstack.infra.v2.UpdateBMCInfoResponse\"\t\xe0\xf3\x18\x02\xea\xf3\x18\x01\x01\x12\x85\x01\n\x13WaitForMachineEvent\x12/.metalstack.infra.v2.WaitForMachineEventRequest\x1a\x30.metalstack.infra.v2.WaitForMachineEventResponse\"\t\xe0\xf3\x18\x02\xea\xf3\x18\x01\x01\x30\x01\x42\xcc\x01\n\x17\x63om.metalstack.infra.v2B\x08\x42mcProtoP\x01Z9github.com/metal-stack/api/go/metalstack/infra/v2;infrav2\xa2\x02\x03MIX\xaa\x02\x13Metalstack.Infra.V2\xca\x02\x13Metalstack\\Infra\\V2\xe2\x02\x1fMetalstack\\Infra\\V2\\GPBMetadata\xea\x02\x15Metalstack::Infra::V2b\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -35,10 +35,16 @@
_globals['DESCRIPTOR']._serialized_options = b'\n\027com.metalstack.infra.v2B\010BmcProtoP\001Z9github.com/metal-stack/api/go/metalstack/infra/v2;infrav2\242\002\003MIX\252\002\023Metalstack.Infra.V2\312\002\023Metalstack\\Infra\\V2\342\002\037Metalstack\\Infra\\V2\\GPBMetadata\352\002\025Metalstack::Infra::V2'
_globals['_BMCSERVICE'].methods_by_name['UpdateBMCInfo']._loaded_options = None
_globals['_BMCSERVICE'].methods_by_name['UpdateBMCInfo']._serialized_options = b'\340\363\030\002\352\363\030\001\001'
+ _globals['_BMCSERVICE'].methods_by_name['WaitForMachineEvent']._loaded_options = None
+ _globals['_BMCSERVICE'].methods_by_name['WaitForMachineEvent']._serialized_options = b'\340\363\030\002\352\363\030\001\001'
_globals['_UPDATEBMCINFOREQUEST']._serialized_start=86
_globals['_UPDATEBMCINFOREQUEST']._serialized_end=108
_globals['_UPDATEBMCINFORESPONSE']._serialized_start=110
_globals['_UPDATEBMCINFORESPONSE']._serialized_end=133
- _globals['_BMCSERVICE']._serialized_start=135
- _globals['_BMCSERVICE']._serialized_end=262
+ _globals['_WAITFORMACHINEEVENTREQUEST']._serialized_start=135
+ _globals['_WAITFORMACHINEEVENTREQUEST']._serialized_end=163
+ _globals['_WAITFORMACHINEEVENTRESPONSE']._serialized_start=165
+ _globals['_WAITFORMACHINEEVENTRESPONSE']._serialized_end=194
+ _globals['_BMCSERVICE']._serialized_start=197
+ _globals['_BMCSERVICE']._serialized_end=460
# @@protoc_insertion_point(module_scope)
diff --git a/python/metalstack/infra/v2/bmc_pb2.pyi b/python/metalstack/infra/v2/bmc_pb2.pyi
index fa266305..64e5eb11 100644
--- a/python/metalstack/infra/v2/bmc_pb2.pyi
+++ b/python/metalstack/infra/v2/bmc_pb2.pyi
@@ -12,3 +12,11 @@ class UpdateBMCInfoRequest(_message.Message):
class UpdateBMCInfoResponse(_message.Message):
__slots__ = ()
def __init__(self) -> None: ...
+
+class WaitForMachineEventRequest(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...
+
+class WaitForMachineEventResponse(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...