move implementation to internal/ directory (#828)

This commit is contained in:
Christian Schwarz
2024-10-18 19:21:17 +02:00
committed by GitHub
parent b9b9ad10cf
commit 908807bd59
360 changed files with 507 additions and 507 deletions
File diff suppressed because it is too large Load Diff
+137
View File
@@ -0,0 +1,137 @@
syntax = "proto3";
option go_package = ".;pdu";
service Replication {
rpc Ping(PingReq) returns (PingRes);
rpc ListFilesystems(ListFilesystemReq) returns (ListFilesystemRes);
rpc ListFilesystemVersions(ListFilesystemVersionsReq)
returns (ListFilesystemVersionsRes);
rpc DestroySnapshots(DestroySnapshotsReq) returns (DestroySnapshotsRes);
rpc ReplicationCursor(ReplicationCursorReq) returns (ReplicationCursorRes);
rpc SendDry(SendReq) returns (SendRes);
rpc SendCompleted(SendCompletedReq) returns (SendCompletedRes);
// for Send and Recv, see package rpc
}
message ListFilesystemReq {}
message ListFilesystemRes { repeated Filesystem Filesystems = 1; }
message Filesystem {
string Path = 1;
string ResumeToken = 2;
bool IsPlaceholder = 3;
}
message ListFilesystemVersionsReq { string Filesystem = 1; }
message ListFilesystemVersionsRes { repeated FilesystemVersion Versions = 1; }
message FilesystemVersion {
enum VersionType {
Snapshot = 0;
Bookmark = 1;
}
VersionType Type = 1;
string Name = 2;
uint64 Guid = 3;
uint64 CreateTXG = 4;
string Creation = 5; // RFC 3339
}
message SendReq {
string Filesystem = 1;
// May be empty / null to request a full transfer of To
FilesystemVersion From = 2;
FilesystemVersion To = 3;
// If ResumeToken is not empty, the resume token that CAN be used for 'zfs
// send' by the sender. The sender MUST indicate use of ResumeToken in the
// reply message SendRes.UsedResumeToken If it does not work, the sender
// SHOULD clear the resume token on their side and use From and To instead If
// ResumeToken is not empty, the GUIDs of From and To MUST correspond to those
// encoded in the ResumeToken. Otherwise, the Sender MUST return an error.
string ResumeToken = 4;
ReplicationConfig ReplicationConfig = 6;
}
message ReplicationConfig {
ReplicationConfigProtection protection = 1;
}
message ReplicationConfigProtection {
ReplicationGuaranteeKind Initial = 1;
ReplicationGuaranteeKind Incremental = 2;
}
enum ReplicationGuaranteeKind {
GuaranteeInvalid = 0;
GuaranteeResumability = 1;
GuaranteeIncrementalReplication = 2;
GuaranteeNothing = 3;
}
message Property {
string Name = 1;
string Value = 2;
}
message SendRes {
// Whether the resume token provided in the request has been used or not.
// If the SendReq.ResumeToken == "", this field MUST be false.
bool UsedResumeToken = 1;
// Expected stream size determined by dry run, not exact.
// 0 indicates that for the given SendReq, no size estimate could be made.
uint64 ExpectedSize = 2;
}
message SendCompletedReq {
SendReq OriginalReq = 2;
}
message SendCompletedRes {}
message ReceiveReq {
string Filesystem = 1;
FilesystemVersion To = 2;
// If true, the receiver should clear the resume token before performing the
// zfs recv of the stream in the request
bool ClearResumeToken = 3;
ReplicationConfig ReplicationConfig = 4;
}
message ReceiveRes {}
message DestroySnapshotsReq {
string Filesystem = 1;
// Path to filesystem, snapshot or bookmark to be destroyed
repeated FilesystemVersion Snapshots = 2;
}
message DestroySnapshotRes {
FilesystemVersion Snapshot = 1;
string Error = 2;
}
message DestroySnapshotsRes { repeated DestroySnapshotRes Results = 1; }
message ReplicationCursorReq { string Filesystem = 1; }
message ReplicationCursorRes {
oneof Result {
uint64 Guid = 1;
bool Notexist = 2;
}
}
message PingReq { string Message = 1; }
message PingRes {
// Echo must be PingReq.Message
string Echo = 1;
}
@@ -0,0 +1,92 @@
package pdu
import (
"fmt"
"time"
"github.com/zrepl/zrepl/internal/zfs"
)
func (v *FilesystemVersion) GetRelName() string {
zv, err := v.ZFSFilesystemVersion()
if err != nil {
return ""
}
return zv.String()
}
func (v *FilesystemVersion) RelName() string {
zv, err := v.ZFSFilesystemVersion()
if err != nil {
panic(err)
}
return zv.String()
}
func (v FilesystemVersion_VersionType) ZFSVersionType() zfs.VersionType {
switch v {
case FilesystemVersion_Snapshot:
return zfs.Snapshot
case FilesystemVersion_Bookmark:
return zfs.Bookmark
default:
panic(fmt.Sprintf("unexpected v.Type %#v", v))
}
}
func FilesystemVersionFromZFS(fsv *zfs.FilesystemVersion) *FilesystemVersion {
var t FilesystemVersion_VersionType
switch fsv.Type {
case zfs.Bookmark:
t = FilesystemVersion_Bookmark
case zfs.Snapshot:
t = FilesystemVersion_Snapshot
default:
panic("unknown fsv.Type: " + fsv.Type)
}
return &FilesystemVersion{
Type: t,
Name: fsv.Name,
Guid: fsv.Guid,
CreateTXG: fsv.CreateTXG,
Creation: fsv.Creation.Format(time.RFC3339),
}
}
func FilesystemVersionCreation(t time.Time) string {
return t.Format(time.RFC3339)
}
func (v *FilesystemVersion) CreationAsTime() (time.Time, error) {
return time.Parse(time.RFC3339, v.Creation)
}
// implement fsfsm.FilesystemVersion
func (v *FilesystemVersion) SnapshotTime() time.Time {
t, err := v.CreationAsTime()
if err != nil {
panic(err) // FIXME
}
return t
}
func (v *FilesystemVersion) ZFSFilesystemVersion() (*zfs.FilesystemVersion, error) {
ct, err := v.CreationAsTime()
if err != nil {
return nil, err
}
return &zfs.FilesystemVersion{
Type: v.Type.ZFSVersionType(),
Name: v.Name,
Guid: v.Guid,
CreateTXG: v.CreateTXG,
Creation: ct,
}, nil
}
func ReplicationConfigProtectionWithKind(both ReplicationGuaranteeKind) *ReplicationConfigProtection {
return &ReplicationConfigProtection{
Initial: both,
Incremental: both,
}
}
@@ -0,0 +1,349 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.28.0
// source: pdu.proto
package pdu
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
Replication_Ping_FullMethodName = "/Replication/Ping"
Replication_ListFilesystems_FullMethodName = "/Replication/ListFilesystems"
Replication_ListFilesystemVersions_FullMethodName = "/Replication/ListFilesystemVersions"
Replication_DestroySnapshots_FullMethodName = "/Replication/DestroySnapshots"
Replication_ReplicationCursor_FullMethodName = "/Replication/ReplicationCursor"
Replication_SendDry_FullMethodName = "/Replication/SendDry"
Replication_SendCompleted_FullMethodName = "/Replication/SendCompleted"
)
// ReplicationClient is the client API for Replication service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type ReplicationClient interface {
Ping(ctx context.Context, in *PingReq, opts ...grpc.CallOption) (*PingRes, error)
ListFilesystems(ctx context.Context, in *ListFilesystemReq, opts ...grpc.CallOption) (*ListFilesystemRes, error)
ListFilesystemVersions(ctx context.Context, in *ListFilesystemVersionsReq, opts ...grpc.CallOption) (*ListFilesystemVersionsRes, error)
DestroySnapshots(ctx context.Context, in *DestroySnapshotsReq, opts ...grpc.CallOption) (*DestroySnapshotsRes, error)
ReplicationCursor(ctx context.Context, in *ReplicationCursorReq, opts ...grpc.CallOption) (*ReplicationCursorRes, error)
SendDry(ctx context.Context, in *SendReq, opts ...grpc.CallOption) (*SendRes, error)
SendCompleted(ctx context.Context, in *SendCompletedReq, opts ...grpc.CallOption) (*SendCompletedRes, error)
}
type replicationClient struct {
cc grpc.ClientConnInterface
}
func NewReplicationClient(cc grpc.ClientConnInterface) ReplicationClient {
return &replicationClient{cc}
}
func (c *replicationClient) Ping(ctx context.Context, in *PingReq, opts ...grpc.CallOption) (*PingRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PingRes)
err := c.cc.Invoke(ctx, Replication_Ping_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *replicationClient) ListFilesystems(ctx context.Context, in *ListFilesystemReq, opts ...grpc.CallOption) (*ListFilesystemRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListFilesystemRes)
err := c.cc.Invoke(ctx, Replication_ListFilesystems_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *replicationClient) ListFilesystemVersions(ctx context.Context, in *ListFilesystemVersionsReq, opts ...grpc.CallOption) (*ListFilesystemVersionsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListFilesystemVersionsRes)
err := c.cc.Invoke(ctx, Replication_ListFilesystemVersions_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *replicationClient) DestroySnapshots(ctx context.Context, in *DestroySnapshotsReq, opts ...grpc.CallOption) (*DestroySnapshotsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DestroySnapshotsRes)
err := c.cc.Invoke(ctx, Replication_DestroySnapshots_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *replicationClient) ReplicationCursor(ctx context.Context, in *ReplicationCursorReq, opts ...grpc.CallOption) (*ReplicationCursorRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ReplicationCursorRes)
err := c.cc.Invoke(ctx, Replication_ReplicationCursor_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *replicationClient) SendDry(ctx context.Context, in *SendReq, opts ...grpc.CallOption) (*SendRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SendRes)
err := c.cc.Invoke(ctx, Replication_SendDry_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *replicationClient) SendCompleted(ctx context.Context, in *SendCompletedReq, opts ...grpc.CallOption) (*SendCompletedRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SendCompletedRes)
err := c.cc.Invoke(ctx, Replication_SendCompleted_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ReplicationServer is the server API for Replication service.
// All implementations must embed UnimplementedReplicationServer
// for forward compatibility.
type ReplicationServer interface {
Ping(context.Context, *PingReq) (*PingRes, error)
ListFilesystems(context.Context, *ListFilesystemReq) (*ListFilesystemRes, error)
ListFilesystemVersions(context.Context, *ListFilesystemVersionsReq) (*ListFilesystemVersionsRes, error)
DestroySnapshots(context.Context, *DestroySnapshotsReq) (*DestroySnapshotsRes, error)
ReplicationCursor(context.Context, *ReplicationCursorReq) (*ReplicationCursorRes, error)
SendDry(context.Context, *SendReq) (*SendRes, error)
SendCompleted(context.Context, *SendCompletedReq) (*SendCompletedRes, error)
mustEmbedUnimplementedReplicationServer()
}
// UnimplementedReplicationServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedReplicationServer struct{}
func (UnimplementedReplicationServer) Ping(context.Context, *PingReq) (*PingRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
}
func (UnimplementedReplicationServer) ListFilesystems(context.Context, *ListFilesystemReq) (*ListFilesystemRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListFilesystems not implemented")
}
func (UnimplementedReplicationServer) ListFilesystemVersions(context.Context, *ListFilesystemVersionsReq) (*ListFilesystemVersionsRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListFilesystemVersions not implemented")
}
func (UnimplementedReplicationServer) DestroySnapshots(context.Context, *DestroySnapshotsReq) (*DestroySnapshotsRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method DestroySnapshots not implemented")
}
func (UnimplementedReplicationServer) ReplicationCursor(context.Context, *ReplicationCursorReq) (*ReplicationCursorRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method ReplicationCursor not implemented")
}
func (UnimplementedReplicationServer) SendDry(context.Context, *SendReq) (*SendRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method SendDry not implemented")
}
func (UnimplementedReplicationServer) SendCompleted(context.Context, *SendCompletedReq) (*SendCompletedRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method SendCompleted not implemented")
}
func (UnimplementedReplicationServer) mustEmbedUnimplementedReplicationServer() {}
func (UnimplementedReplicationServer) testEmbeddedByValue() {}
// UnsafeReplicationServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ReplicationServer will
// result in compilation errors.
type UnsafeReplicationServer interface {
mustEmbedUnimplementedReplicationServer()
}
func RegisterReplicationServer(s grpc.ServiceRegistrar, srv ReplicationServer) {
// If the following call pancis, it indicates UnimplementedReplicationServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&Replication_ServiceDesc, srv)
}
func _Replication_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PingReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).Ping(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_Ping_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).Ping(ctx, req.(*PingReq))
}
return interceptor(ctx, in, info, handler)
}
func _Replication_ListFilesystems_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListFilesystemReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).ListFilesystems(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_ListFilesystems_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).ListFilesystems(ctx, req.(*ListFilesystemReq))
}
return interceptor(ctx, in, info, handler)
}
func _Replication_ListFilesystemVersions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListFilesystemVersionsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).ListFilesystemVersions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_ListFilesystemVersions_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).ListFilesystemVersions(ctx, req.(*ListFilesystemVersionsReq))
}
return interceptor(ctx, in, info, handler)
}
func _Replication_DestroySnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DestroySnapshotsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).DestroySnapshots(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_DestroySnapshots_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).DestroySnapshots(ctx, req.(*DestroySnapshotsReq))
}
return interceptor(ctx, in, info, handler)
}
func _Replication_ReplicationCursor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReplicationCursorReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).ReplicationCursor(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_ReplicationCursor_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).ReplicationCursor(ctx, req.(*ReplicationCursorReq))
}
return interceptor(ctx, in, info, handler)
}
func _Replication_SendDry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SendReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).SendDry(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_SendDry_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).SendDry(ctx, req.(*SendReq))
}
return interceptor(ctx, in, info, handler)
}
func _Replication_SendCompleted_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SendCompletedReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReplicationServer).SendCompleted(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Replication_SendCompleted_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReplicationServer).SendCompleted(ctx, req.(*SendCompletedReq))
}
return interceptor(ctx, in, info, handler)
}
// Replication_ServiceDesc is the grpc.ServiceDesc for Replication service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Replication_ServiceDesc = grpc.ServiceDesc{
ServiceName: "Replication",
HandlerType: (*ReplicationServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Ping",
Handler: _Replication_Ping_Handler,
},
{
MethodName: "ListFilesystems",
Handler: _Replication_ListFilesystems_Handler,
},
{
MethodName: "ListFilesystemVersions",
Handler: _Replication_ListFilesystemVersions_Handler,
},
{
MethodName: "DestroySnapshots",
Handler: _Replication_DestroySnapshots_Handler,
},
{
MethodName: "ReplicationCursor",
Handler: _Replication_ReplicationCursor_Handler,
},
{
MethodName: "SendDry",
Handler: _Replication_SendDry_Handler,
},
{
MethodName: "SendCompleted",
Handler: _Replication_SendCompleted_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "pdu.proto",
}
@@ -0,0 +1,69 @@
package pdu
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestFilesystemVersion_RelName(t *testing.T) {
type TestCase struct {
In *FilesystemVersion
Out string
Panic bool
}
creat := FilesystemVersionCreation(time.Now())
tcs := []TestCase{
{
In: &FilesystemVersion{
Type: FilesystemVersion_Snapshot,
Name: "foobar",
Creation: creat,
},
Out: "@foobar",
},
{
In: &FilesystemVersion{
Type: FilesystemVersion_Bookmark,
Name: "foobar",
Creation: creat,
},
Out: "#foobar",
},
{
In: &FilesystemVersion{
Type: 2342,
Name: "foobar",
Creation: creat,
},
Panic: true,
},
}
for _, tc := range tcs {
if tc.Panic {
assert.Panics(t, func() {
tc.In.RelName()
})
} else {
o := tc.In.RelName()
assert.Equal(t, tc.Out, o)
}
}
}
func TestFilesystemVersion_ZFSFilesystemVersion(t *testing.T) {
empty := &FilesystemVersion{}
_, err := empty.ZFSFilesystemVersion()
assert.Error(t, err)
dateInvalid := &FilesystemVersion{Creation: "foobar"}
_, err = dateInvalid.ZFSFilesystemVersion()
assert.Error(t, err)
}