From 387b850e5ef667ca99e5d4f883f52442fc82514b Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 24 Apr 2024 16:00:37 +0300 Subject: [PATCH] [#74] apemanager: Generate protobufs for apemanager service * Generate protobufs. * Make marshallers, unmarshallers, json-encoders etc. * Create message encoding/decoding unit-tests. Signed-off-by: Airat Arifullin --- apemanager/convert.go | 481 +++++++++++++++++++++++++++++ apemanager/grpc/service.go | 105 +++++++ apemanager/grpc/service.pb.go | Bin 0 -> 46612 bytes apemanager/grpc/service_grpc.pb.go | Bin 0 -> 9993 bytes apemanager/grpc/types.go | 21 ++ apemanager/grpc/types.pb.go | Bin 0 -> 9919 bytes apemanager/json.go | 14 + apemanager/marshal.go | 288 +++++++++++++++++ apemanager/message_test.go | 27 ++ apemanager/status.go | 76 +++++ apemanager/status_test.go | 30 ++ apemanager/string.go | 18 ++ apemanager/test/generate.go | 208 +++++++++++++ apemanager/types.go | 244 +++++++++++++++ rpc/apemanager.go | 60 ++++ signature/body.go | 15 + status/grpc/types.pb.go | Bin 22080 -> 23790 bytes 17 files changed, 1587 insertions(+) create mode 100644 apemanager/convert.go create mode 100644 apemanager/grpc/service.go create mode 100644 apemanager/grpc/service.pb.go create mode 100644 apemanager/grpc/service_grpc.pb.go create mode 100644 apemanager/grpc/types.go create mode 100644 apemanager/grpc/types.pb.go create mode 100644 apemanager/json.go create mode 100644 apemanager/marshal.go create mode 100644 apemanager/message_test.go create mode 100644 apemanager/status.go create mode 100644 apemanager/status_test.go create mode 100644 apemanager/string.go create mode 100644 apemanager/test/generate.go create mode 100644 apemanager/types.go create mode 100644 rpc/apemanager.go diff --git a/apemanager/convert.go b/apemanager/convert.go new file mode 100644 index 00000000..12b087c3 --- /dev/null +++ b/apemanager/convert.go @@ -0,0 +1,481 @@ +package apemanager + +import ( + "fmt" + + apemanager "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" +) + +func TargetTypeToGRPCField(typ TargetType) apemanager.TargetType { + switch typ { + case TargetTypeNamespace: + return apemanager.TargetType_NAMESPACE + case TargetTypeContainer: + return apemanager.TargetType_CONTAINER + case TargetTypeUser: + return apemanager.TargetType_USER + case TargetTypeGroup: + return apemanager.TargetType_GROUP + default: + return apemanager.TargetType_UNDEFINED + } +} + +func TargetTypeFromGRPCField(typ apemanager.TargetType) TargetType { + switch typ { + case apemanager.TargetType_NAMESPACE: + return TargetTypeNamespace + case apemanager.TargetType_CONTAINER: + return TargetTypeContainer + case apemanager.TargetType_USER: + return TargetTypeUser + case apemanager.TargetType_GROUP: + return TargetTypeGroup + default: + return TargetTypeUndefined + } +} + +func TargetTypeToGRPC(typ TargetType) apemanager.TargetType { + return apemanager.TargetType(typ) +} + +func TargetTypeFromGRPC(typ apemanager.TargetType) TargetType { + return TargetType(typ) +} + +func (v2 *ChainTarget) ToGRPCMessage() grpc.Message { + var mgrpc *apemanager.ChainTarget + + if v2 != nil { + mgrpc = new(apemanager.ChainTarget) + + mgrpc.SetType(TargetTypeToGRPC(v2.GetTargetType())) + mgrpc.SetName(v2.GetName()) + } + + return mgrpc +} + +func (v2 *ChainTarget) FromGRPCMessage(m grpc.Message) error { + mgrpc, ok := m.(*apemanager.ChainTarget) + if !ok { + return message.NewUnexpectedMessageType(m, mgrpc) + } + + v2.SetTargetType(TargetTypeFromGRPC(mgrpc.GetType())) + v2.SetName(mgrpc.GetName()) + + return nil +} + +func (v2 *ChainRaw) ToGRPCMessage() grpc.Message { + var mgrpc *apemanager.Chain_Raw + + if v2 != nil { + mgrpc = new(apemanager.Chain_Raw) + + mgrpc.SetRaw(v2.GetRaw()) + } + + return mgrpc +} + +func (v2 *ChainRaw) FromGRPCMessage(m grpc.Message) error { + mgrpc, ok := m.(*apemanager.Chain_Raw) + if !ok { + return message.NewUnexpectedMessageType(m, mgrpc) + } + + v2.SetRaw(mgrpc.GetRaw()) + + return nil +} + +func (v2 *Chain) ToGRPCMessage() grpc.Message { + var mgrpc *apemanager.Chain + + if v2 != nil { + mgrpc = new(apemanager.Chain) + + switch chainKind := v2.GetKind().(type) { + default: + panic(fmt.Sprintf("unsupported chain kind: %T", chainKind)) + case *ChainRaw: + mgrpc.SetKind(chainKind.ToGRPCMessage().(*apemanager.Chain_Raw)) + } + } + + return mgrpc +} + +func (v2 *Chain) FromGRPCMessage(m grpc.Message) error { + mgrpc, ok := m.(*apemanager.Chain) + if !ok { + return message.NewUnexpectedMessageType(m, mgrpc) + } + + switch chainKind := mgrpc.GetKind().(type) { + default: + return fmt.Errorf("unsupported chain kind: %T", chainKind) + case *apemanager.Chain_Raw: + chainRaw := new(ChainRaw) + if err := chainRaw.FromGRPCMessage(chainKind); err != nil { + return err + } + v2.SetKind(chainRaw) + } + + return nil +} + +func (reqBody *AddChainRequestBody) ToGRPCMessage() grpc.Message { + var reqBodygrpc *apemanager.AddChainRequest_Body + + if reqBody != nil { + reqBodygrpc = new(apemanager.AddChainRequest_Body) + + reqBodygrpc.SetTarget(reqBody.GetTarget().ToGRPCMessage().(*apemanager.ChainTarget)) + reqBodygrpc.SetChain(reqBody.GetChain().ToGRPCMessage().(*apemanager.Chain)) + } + + return reqBodygrpc +} + +func (reqBody *AddChainRequestBody) FromGRPCMessage(m grpc.Message) error { + reqBodygrpc, ok := m.(*apemanager.AddChainRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, reqBodygrpc) + } + + if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil { + reqBody.target = new(ChainTarget) + if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil { + return err + } + } + + if chaingrpc := reqBodygrpc.GetChain(); chaingrpc != nil { + reqBody.chain = new(Chain) + if err := reqBody.GetChain().FromGRPCMessage(chaingrpc); err != nil { + return err + } + } + + return nil +} + +func (req *AddChainRequest) ToGRPCMessage() grpc.Message { + var reqgrpc *apemanager.AddChainRequest + + if req != nil { + reqgrpc = new(apemanager.AddChainRequest) + + reqgrpc.SetBody(req.GetBody().ToGRPCMessage().(*apemanager.AddChainRequest_Body)) + req.RequestHeaders.ToMessage(reqgrpc) + } + + return reqgrpc +} + +func (req *AddChainRequest) FromGRPCMessage(m grpc.Message) error { + reqgrpc, ok := m.(*apemanager.AddChainRequest) + if !ok { + return message.NewUnexpectedMessageType(m, reqgrpc) + } + + if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil { + req.body = new(AddChainRequestBody) + if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil { + return err + } + } + + return req.RequestHeaders.FromMessage(reqgrpc) +} + +func (respBody *AddChainResponseBody) ToGRPCMessage() grpc.Message { + var respBodygrpc *apemanager.AddChainResponse_Body + + if respBody != nil { + respBodygrpc = new(apemanager.AddChainResponse_Body) + + respBodygrpc.SetChainID(respBody.GetChainID()) + } + + return respBodygrpc +} + +func (respBody *AddChainResponseBody) FromGRPCMessage(m grpc.Message) error { + respBodygrpc, ok := m.(*apemanager.AddChainResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, respBodygrpc) + } + + respBody.SetChainID(respBodygrpc.GetChainId()) + + return nil +} + +func (resp *AddChainResponse) ToGRPCMessage() grpc.Message { + var respgrpc *apemanager.AddChainResponse + + if resp != nil { + respgrpc = new(apemanager.AddChainResponse) + + respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.AddChainResponse_Body)) + resp.ResponseHeaders.ToMessage(respgrpc) + } + + return respgrpc +} + +func (resp *AddChainResponse) FromGRPCMessage(m grpc.Message) error { + respgrpc, ok := m.(*apemanager.AddChainResponse) + if !ok { + return message.NewUnexpectedMessageType(m, respgrpc) + } + + if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil { + resp.body = new(AddChainResponseBody) + if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil { + return err + } + } + + return resp.ResponseHeaders.FromMessage(respgrpc) +} + +func (reqBody *RemoveChainRequestBody) ToGRPCMessage() grpc.Message { + var reqBodygrpc *apemanager.RemoveChainRequest_Body + + if reqBody != nil { + reqBodygrpc = new(apemanager.RemoveChainRequest_Body) + + reqBodygrpc.SetTarget(reqBody.target.ToGRPCMessage().(*apemanager.ChainTarget)) + reqBodygrpc.SetChainID(reqBody.GetChainID()) + } + + return reqBodygrpc +} + +func (reqBody *RemoveChainRequestBody) FromGRPCMessage(m grpc.Message) error { + reqBodygrpc, ok := m.(*apemanager.RemoveChainRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, reqBodygrpc) + } + + if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil { + reqBody.target = new(ChainTarget) + if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil { + return err + } + } + + reqBody.SetChainID(reqBodygrpc.GetChainId()) + + return nil +} + +func (req *RemoveChainRequest) ToGRPCMessage() grpc.Message { + var reqgrpc *apemanager.RemoveChainRequest + + if req != nil { + reqgrpc = new(apemanager.RemoveChainRequest) + + reqgrpc.SetBody(req.body.ToGRPCMessage().(*apemanager.RemoveChainRequest_Body)) + req.RequestHeaders.ToMessage(reqgrpc) + } + + return reqgrpc +} + +func (req *RemoveChainRequest) FromGRPCMessage(m grpc.Message) error { + reqgrpc, ok := m.(*apemanager.RemoveChainRequest) + if !ok { + return message.NewUnexpectedMessageType(m, reqgrpc) + } + + if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil { + req.body = new(RemoveChainRequestBody) + if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil { + return err + } + } + + return req.RequestHeaders.FromMessage(reqgrpc) +} + +func (respBody *RemoveChainResponseBody) ToGRPCMessage() grpc.Message { + var respBodygrpc *apemanager.RemoveChainResponse_Body + + if respBody != nil { + respBodygrpc = new(apemanager.RemoveChainResponse_Body) + } + + return respBodygrpc +} + +func (respBody *RemoveChainResponseBody) FromGRPCMessage(m grpc.Message) error { + respBodygrpc, ok := m.(*apemanager.RemoveChainResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, respBodygrpc) + } + + return nil +} + +func (resp *RemoveChainResponse) ToGRPCMessage() grpc.Message { + var respgrpc *apemanager.RemoveChainResponse + + if resp != nil { + respgrpc = new(apemanager.RemoveChainResponse) + + respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.RemoveChainResponse_Body)) + resp.ResponseHeaders.ToMessage(respgrpc) + } + + return respgrpc +} + +func (resp *RemoveChainResponse) FromGRPCMessage(m grpc.Message) error { + respgrpc, ok := m.(*apemanager.RemoveChainResponse) + if !ok { + return message.NewUnexpectedMessageType(m, respgrpc) + } + + if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil { + resp.body = new(RemoveChainResponseBody) + if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil { + return err + } + } + + return resp.ResponseHeaders.FromMessage(respgrpc) +} + +func (reqBody *ListChainsRequestBody) ToGRPCMessage() grpc.Message { + var reqBodygrpc *apemanager.ListChainsRequest_Body + + if reqBody != nil { + reqBodygrpc = new(apemanager.ListChainsRequest_Body) + + reqBodygrpc.SetTarget(reqBody.target.ToGRPCMessage().(*apemanager.ChainTarget)) + } + + return reqBodygrpc +} + +func (reqBody *ListChainsRequestBody) FromGRPCMessage(m grpc.Message) error { + reqBodygrpc, ok := m.(*apemanager.ListChainsRequest_Body) + if !ok { + return message.NewUnexpectedMessageType(m, reqBodygrpc) + } + + if targetgrpc := reqBodygrpc.GetTarget(); targetgrpc != nil { + reqBody.target = new(ChainTarget) + if err := reqBody.target.FromGRPCMessage(targetgrpc); err != nil { + return err + } + } + + return nil +} + +func (req *ListChainsRequest) ToGRPCMessage() grpc.Message { + var reqgrpc *apemanager.ListChainsRequest + + if req != nil { + reqgrpc = new(apemanager.ListChainsRequest) + + reqgrpc.SetBody(req.body.ToGRPCMessage().(*apemanager.ListChainsRequest_Body)) + req.RequestHeaders.ToMessage(reqgrpc) + } + + return reqgrpc +} + +func (req *ListChainsRequest) FromGRPCMessage(m grpc.Message) error { + reqgrpc, ok := m.(*apemanager.ListChainsRequest) + if !ok { + return message.NewUnexpectedMessageType(m, reqgrpc) + } + + if reqBodygrpc := reqgrpc.GetBody(); reqBodygrpc != nil { + req.body = new(ListChainsRequestBody) + if err := req.body.FromGRPCMessage(reqBodygrpc); err != nil { + return err + } + } + + return req.RequestHeaders.FromMessage(reqgrpc) +} + +func (respBody *ListChainsResponseBody) ToGRPCMessage() grpc.Message { + var respBodygrpc *apemanager.ListChainsResponse_Body + + if respBody != nil { + respBodygrpc = new(apemanager.ListChainsResponse_Body) + + chainsgrpc := make([]*apemanager.Chain, 0, len(respBody.GetChains())) + for _, chain := range respBody.GetChains() { + chainsgrpc = append(chainsgrpc, chain.ToGRPCMessage().(*apemanager.Chain)) + } + + respBodygrpc.SetChains(chainsgrpc) + } + + return respBodygrpc +} + +func (respBody *ListChainsResponseBody) FromGRPCMessage(m grpc.Message) error { + respBodygrpc, ok := m.(*apemanager.ListChainsResponse_Body) + if !ok { + return message.NewUnexpectedMessageType(m, respBodygrpc) + } + + chains := make([]*Chain, 0, len(respBodygrpc.GetChains())) + + for _, chaingrpc := range respBodygrpc.GetChains() { + chain := new(Chain) + if err := chain.FromGRPCMessage(chaingrpc); err != nil { + return err + } + chains = append(chains, chain) + } + + respBody.SetChains(chains) + + return nil +} + +func (resp *ListChainsResponse) ToGRPCMessage() grpc.Message { + var respgrpc *apemanager.ListChainsResponse + + if resp != nil { + respgrpc = new(apemanager.ListChainsResponse) + + respgrpc.SetBody(resp.body.ToGRPCMessage().(*apemanager.ListChainsResponse_Body)) + resp.ResponseHeaders.ToMessage(respgrpc) + } + + return respgrpc +} + +func (resp *ListChainsResponse) FromGRPCMessage(m grpc.Message) error { + respgrpc, ok := m.(*apemanager.ListChainsResponse) + if !ok { + return message.NewUnexpectedMessageType(m, respgrpc) + } + + if respBodygrpc := respgrpc.GetBody(); respBodygrpc != nil { + resp.body = new(ListChainsResponseBody) + if err := resp.body.FromGRPCMessage(respBodygrpc); err != nil { + return err + } + } + + return resp.ResponseHeaders.FromMessage(respgrpc) +} diff --git a/apemanager/grpc/service.go b/apemanager/grpc/service.go new file mode 100644 index 00000000..89ffa716 --- /dev/null +++ b/apemanager/grpc/service.go @@ -0,0 +1,105 @@ +package apemanager + +import ( + session_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" +) + +func (rb *AddChainRequest_Body) SetTarget(t *ChainTarget) { + rb.Target = t +} + +func (rb *AddChainRequest_Body) SetChain(chain *Chain) { + rb.Chain = chain +} + +func (r *AddChainRequest) SetBody(rb *AddChainRequest_Body) { + r.Body = rb +} + +func (r *AddChainRequest) SetMetaHeader(mh *session_grpc.RequestMetaHeader) { + r.MetaHeader = mh +} + +func (r *AddChainRequest) SetVerifyHeader(vh *session_grpc.RequestVerificationHeader) { + r.VerifyHeader = vh +} + +func (rb *AddChainResponse_Body) SetChainID(chainID []byte) { + rb.ChainId = chainID +} + +func (r *AddChainResponse) SetBody(rb *AddChainResponse_Body) { + r.Body = rb +} + +func (r *AddChainResponse) SetMetaHeader(mh *session_grpc.ResponseMetaHeader) { + r.MetaHeader = mh +} + +func (r *AddChainResponse) SetVerifyHeader(vh *session_grpc.ResponseVerificationHeader) { + r.VerifyHeader = vh +} + +func (rb *RemoveChainRequest_Body) SetTarget(t *ChainTarget) { + rb.Target = t +} + +func (rb *RemoveChainRequest_Body) SetChainID(chainID []byte) { + rb.ChainId = chainID +} + +func (r *RemoveChainRequest) SetBody(rb *RemoveChainRequest_Body) { + r.Body = rb +} + +func (r *RemoveChainRequest) SetMetaHeader(mh *session_grpc.RequestMetaHeader) { + r.MetaHeader = mh +} + +func (r *RemoveChainRequest) SetVerifyHeader(vh *session_grpc.RequestVerificationHeader) { + r.VerifyHeader = vh +} + +func (r *RemoveChainResponse) SetBody(rb *RemoveChainResponse_Body) { + r.Body = rb +} + +func (r *RemoveChainResponse) SetMetaHeader(mh *session_grpc.ResponseMetaHeader) { + r.MetaHeader = mh +} + +func (r *RemoveChainResponse) SetVerifyHeader(vh *session_grpc.ResponseVerificationHeader) { + r.VerifyHeader = vh +} + +func (r *ListChainsRequest_Body) SetTarget(t *ChainTarget) { + r.Target = t +} + +func (r *ListChainsRequest) SetBody(rb *ListChainsRequest_Body) { + r.Body = rb +} + +func (r *ListChainsRequest) SetMetaHeader(mh *session_grpc.RequestMetaHeader) { + r.MetaHeader = mh +} + +func (r *ListChainsRequest) SetVerifyHeader(vh *session_grpc.RequestVerificationHeader) { + r.VerifyHeader = vh +} + +func (rb *ListChainsResponse_Body) SetChains(chains []*Chain) { + rb.Chains = chains +} + +func (r *ListChainsResponse) SetBody(rb *ListChainsResponse_Body) { + r.Body = rb +} + +func (r *ListChainsResponse) SetMetaHeader(mh *session_grpc.ResponseMetaHeader) { + r.MetaHeader = mh +} + +func (r *ListChainsResponse) SetVerifyHeader(vh *session_grpc.ResponseVerificationHeader) { + r.VerifyHeader = vh +} diff --git a/apemanager/grpc/service.pb.go b/apemanager/grpc/service.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..157da44ac165633bff370a856b1da296de6c6b88 GIT binary patch literal 46612 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 ZnoY*1rs6WoBhJ2qU%f)c`Mb~&{sEO)%c=kX