mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-01-03 11:45:20 +00:00
Added ItemSnapshotter.proto Added item_snapshotter Go interface Added framework components for item_snapshotter Updated plugins doc with ItemSnapshotter info Added SnapshotPhase to item_snapshotter.go ProgressOutputOutput now includes a phase as well as an error string for problems that occured Signed-off-by: Dave Smith-Uchida <dsmithuchida@vmware.com>
This commit is contained in:
committed by
GitHub
parent
0a19b394e2
commit
5150ce4891
44
pkg/plugin/framework/item_snapshotter.go
Normal file
44
pkg/plugin/framework/item_snapshotter.go
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package framework
|
||||
|
||||
import (
|
||||
plugin "github.com/hashicorp/go-plugin"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
|
||||
)
|
||||
|
||||
// ItemSnapshotterPlugin is an implementation of go-plugin's Plugin
|
||||
// interface with support for gRPC for the ItemSnapshotter
|
||||
// interface.
|
||||
type ItemSnapshotterPlugin struct {
|
||||
plugin.NetRPCUnsupportedPlugin
|
||||
*pluginBase
|
||||
}
|
||||
|
||||
// GRPCClient returns a clientDispenser for ItemSnapshotter gRPC clients.
|
||||
func (p *ItemSnapshotterPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) {
|
||||
return newClientDispenser(p.clientLogger, clientConn, newItemSnapshotterGRPCClient), nil
|
||||
}
|
||||
|
||||
// GRPCServer registers an ItemSnapshotter gRPC server.
|
||||
func (p *ItemSnapshotterPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error {
|
||||
proto.RegisterItemSnapshotterServer(server, &ItemSnapshotterGRPCServer{mux: p.serverMux})
|
||||
return nil
|
||||
}
|
||||
240
pkg/plugin/framework/item_snapshotter_client.go
Normal file
240
pkg/plugin/framework/item_snapshotter_client.go
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package framework
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// NewItemSnapshotterPlugin constructs a ItemSnapshotterPlugin.
|
||||
func NewItemSnapshotterPlugin(options ...PluginOption) *ItemSnapshotterPlugin {
|
||||
return &ItemSnapshotterPlugin{
|
||||
pluginBase: newPluginBase(options...),
|
||||
}
|
||||
}
|
||||
|
||||
func newItemSnapshotterGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} {
|
||||
return &ItemSnapshotterGRPCClient{
|
||||
clientBase: base,
|
||||
grpcClient: proto.NewItemSnapshotterClient(clientConn),
|
||||
}
|
||||
}
|
||||
|
||||
// ItemSnapshotterGRPCClient implements the ItemSnapshotter interface and uses a
|
||||
// gRPC client to make calls to the plugin server.
|
||||
type ItemSnapshotterGRPCClient struct {
|
||||
*clientBase
|
||||
grpcClient proto.ItemSnapshotterClient
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) Init(config map[string]string) error {
|
||||
req := &proto.ItemSnapshotterInitRequest{
|
||||
Plugin: recv.plugin,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
_, err := recv.grpcClient.Init(context.Background(), req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) AppliesTo() (velero.ResourceSelector, error) {
|
||||
req := &proto.ItemSnapshotterAppliesToRequest{
|
||||
Plugin: recv.plugin,
|
||||
}
|
||||
|
||||
res, err := recv.grpcClient.AppliesTo(context.Background(), req)
|
||||
if err != nil {
|
||||
return velero.ResourceSelector{}, fromGRPCError(err)
|
||||
}
|
||||
|
||||
if res.ResourceSelector == nil {
|
||||
return velero.ResourceSelector{}, nil
|
||||
}
|
||||
|
||||
return velero.ResourceSelector{
|
||||
IncludedNamespaces: res.ResourceSelector.IncludedNamespaces,
|
||||
ExcludedNamespaces: res.ResourceSelector.ExcludedNamespaces,
|
||||
IncludedResources: res.ResourceSelector.IncludedResources,
|
||||
ExcludedResources: res.ResourceSelector.ExcludedResources,
|
||||
LabelSelector: res.ResourceSelector.Selector,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) AlsoHandles(input *isv1.AlsoHandlesInput) ([]velero.ResourceIdentifier, error) {
|
||||
itemJSON, err := json.Marshal(input.Item.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
backupJSON, err := json.Marshal(input.Backup)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
req := &proto.AlsoHandlesRequest{
|
||||
Plugin: recv.plugin,
|
||||
Item: itemJSON,
|
||||
Backup: backupJSON,
|
||||
}
|
||||
res, err := recv.grpcClient.AlsoHandles(context.Background(), req)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
handledItems := unpackResourceIdentifiers(res.HandledItems)
|
||||
|
||||
return handledItems, nil
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) SnapshotItem(ctx context.Context, input *isv1.SnapshotItemInput) (*isv1.SnapshotItemOutput, error) {
|
||||
itemJSON, err := json.Marshal(input.Item.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
backupJSON, err := json.Marshal(input.Backup)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
req := &proto.SnapshotItemRequest{
|
||||
Plugin: recv.plugin,
|
||||
Item: itemJSON,
|
||||
Backup: backupJSON,
|
||||
}
|
||||
res, err := recv.grpcClient.SnapshotItem(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
var updatedItem unstructured.Unstructured
|
||||
if err := json.Unmarshal(res.Item, &updatedItem); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
additionalItems := unpackResourceIdentifiers(res.AdditionalItems)
|
||||
handledItems := unpackResourceIdentifiers(res.HandledItems)
|
||||
|
||||
sio := isv1.SnapshotItemOutput{
|
||||
UpdatedItem: &updatedItem,
|
||||
SnapshotID: res.SnapshotID,
|
||||
SnapshotMetadata: res.SnapshotMetadata,
|
||||
AdditionalItems: additionalItems,
|
||||
HandledItems: handledItems,
|
||||
}
|
||||
return &sio, nil
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) Progress(input *isv1.ProgressInput) (*isv1.ProgressOutput, error) {
|
||||
backupJSON, err := json.Marshal(input.Backup)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
req := &proto.ProgressRequest{
|
||||
Plugin: recv.plugin,
|
||||
ItemID: resourceIdentifierToProto(input.ItemID),
|
||||
SnapshotID: input.SnapshotID,
|
||||
Backup: backupJSON,
|
||||
}
|
||||
|
||||
res, err := recv.grpcClient.Progress(context.Background(), req)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
// Validate phase
|
||||
|
||||
phase, err := isv1.SnapshotPhaseFromString(res.Phase)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
up := isv1.ProgressOutput{
|
||||
Phase: phase,
|
||||
Err: res.Err,
|
||||
ItemsCompleted: res.ItemsCompleted,
|
||||
ItemsToComplete: res.ItemsToComplete,
|
||||
Started: time.Unix(res.Started, res.StartedNano),
|
||||
Updated: time.Unix(res.Updated, res.UpdatedNano),
|
||||
}
|
||||
return &up, nil
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) DeleteSnapshot(ctx context.Context, input *isv1.DeleteSnapshotInput) error {
|
||||
req := &proto.DeleteItemSnapshotRequest{
|
||||
Plugin: recv.plugin,
|
||||
Params: input.Params,
|
||||
SnapshotID: input.SnapshotID,
|
||||
}
|
||||
_, err := recv.grpcClient.DeleteSnapshot(ctx, req) // Returns Empty as first arg so just ignore
|
||||
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (recv ItemSnapshotterGRPCClient) CreateItemFromSnapshot(ctx context.Context, input *isv1.CreateItemInput) (*isv1.CreateItemOutput, error) {
|
||||
itemJSON, err := json.Marshal(input.SnapshottedItem.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
itemFromBackupJSON, err := json.Marshal(input.ItemFromBackup.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
restoreJSON, err := json.Marshal(input.Restore)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
req := &proto.CreateItemFromSnapshotRequest{
|
||||
Plugin: recv.plugin,
|
||||
Item: itemJSON,
|
||||
SnapshotID: input.SnapshotID,
|
||||
ItemFromBackup: itemFromBackupJSON,
|
||||
SnapshotMetadata: input.SnapshotMetadata,
|
||||
Params: input.Params,
|
||||
Restore: restoreJSON,
|
||||
}
|
||||
|
||||
res, err := recv.grpcClient.CreateItemFromSnapshot(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
var updatedItem unstructured.Unstructured
|
||||
if err := json.Unmarshal(res.Item, &updatedItem); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
additionalItems := unpackResourceIdentifiers(res.AdditionalItems)
|
||||
|
||||
cio := isv1.CreateItemOutput{
|
||||
UpdatedItem: &updatedItem,
|
||||
AdditionalItems: additionalItems,
|
||||
SkipRestore: res.SkipRestore,
|
||||
}
|
||||
return &cio, nil
|
||||
}
|
||||
311
pkg/plugin/framework/item_snapshotter_server.go
Normal file
311
pkg/plugin/framework/item_snapshotter_server.go
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package framework
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
|
||||
)
|
||||
|
||||
// ItemSnapshotterGRPCServer implements the proto-generated ItemSnapshotterServer interface, and accepts
|
||||
// gRPC calls and forwards them to an implementation of the pluggable interface.
|
||||
type ItemSnapshotterGRPCServer struct {
|
||||
mux *serverMux
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) getImpl(name string) (isv1.ItemSnapshotter, error) {
|
||||
impl, err := recv.mux.getHandler(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
itemAction, ok := impl.(isv1.ItemSnapshotter)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not an item snapshotter", impl)
|
||||
}
|
||||
|
||||
return itemAction, nil
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) Init(c context.Context, req *proto.ItemSnapshotterInitRequest) (response *proto.Empty, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
err = impl.Init(req.Config)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
return &proto.Empty{}, nil
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) AppliesTo(ctx context.Context, req *proto.ItemSnapshotterAppliesToRequest) (response *proto.ItemSnapshotterAppliesToResponse, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
resourceSelector, err := impl.AppliesTo()
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
return &proto.ItemSnapshotterAppliesToResponse{
|
||||
&proto.ResourceSelector{
|
||||
IncludedNamespaces: resourceSelector.IncludedNamespaces,
|
||||
ExcludedNamespaces: resourceSelector.ExcludedNamespaces,
|
||||
IncludedResources: resourceSelector.IncludedResources,
|
||||
ExcludedResources: resourceSelector.ExcludedResources,
|
||||
Selector: resourceSelector.LabelSelector,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) AlsoHandles(ctx context.Context, req *proto.AlsoHandlesRequest) (res *proto.AlsoHandlesResponse, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
var item unstructured.Unstructured
|
||||
var backup api.Backup
|
||||
|
||||
if err := json.Unmarshal(req.Item, &item); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
if err := json.Unmarshal(req.Backup, &backup); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
ahi := isv1.AlsoHandlesInput{
|
||||
Item: &item,
|
||||
Backup: &backup,
|
||||
}
|
||||
alsoHandles, err := impl.AlsoHandles(&ahi)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
res = &proto.AlsoHandlesResponse{}
|
||||
|
||||
for _, item := range alsoHandles {
|
||||
res.HandledItems = append(res.HandledItems, resourceIdentifierToProto(item))
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) SnapshotItem(ctx context.Context, req *proto.SnapshotItemRequest) (res *proto.SnapshotItemResponse, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
var item unstructured.Unstructured
|
||||
var backup api.Backup
|
||||
|
||||
if err := json.Unmarshal(req.Item, &item); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
if err := json.Unmarshal(req.Backup, &backup); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
sii := isv1.SnapshotItemInput{
|
||||
Item: &item,
|
||||
Params: req.Params,
|
||||
Backup: &backup,
|
||||
}
|
||||
sio, err := impl.SnapshotItem(ctx, &sii)
|
||||
|
||||
// If the plugin implementation returned a nil updatedItem (meaning no modifications), reset updatedItem to the
|
||||
// original item.
|
||||
var updatedItemJSON []byte
|
||||
if sio.UpdatedItem == nil {
|
||||
updatedItemJSON = req.Item
|
||||
} else {
|
||||
updatedItemJSON, err = json.Marshal(sio.UpdatedItem.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
}
|
||||
res = &proto.SnapshotItemResponse{
|
||||
Item: updatedItemJSON,
|
||||
SnapshotID: sio.SnapshotID,
|
||||
SnapshotMetadata: sio.SnapshotMetadata,
|
||||
}
|
||||
res.AdditionalItems = packResourceIdentifiers(sio.AdditionalItems)
|
||||
res.HandledItems = packResourceIdentifiers(sio.HandledItems)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) Progress(ctx context.Context, req *proto.ProgressRequest) (res *proto.ProgressResponse, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
var backup api.Backup
|
||||
|
||||
if err := json.Unmarshal(req.Backup, &backup); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
sipi := &isv1.ProgressInput{
|
||||
ItemID: protoToResourceIdentifier(req.ItemID),
|
||||
SnapshotID: req.SnapshotID,
|
||||
Backup: &backup,
|
||||
}
|
||||
|
||||
sipo, err := impl.Progress(sipi)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
res = &proto.ProgressResponse{
|
||||
Phase: string(sipo.Phase),
|
||||
ItemsCompleted: sipo.ItemsCompleted,
|
||||
ItemsToComplete: sipo.ItemsToComplete,
|
||||
Started: sipo.Started.Unix(),
|
||||
StartedNano: sipo.Started.UnixNano(),
|
||||
Updated: sipo.Updated.Unix(),
|
||||
UpdatedNano: sipo.Updated.UnixNano(),
|
||||
Err: sipo.Err,
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) DeleteSnapshot(ctx context.Context, req *proto.DeleteItemSnapshotRequest) (empty *proto.Empty, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
var itemFromBackup unstructured.Unstructured
|
||||
if err := json.Unmarshal(req.ItemFromBackup, &itemFromBackup); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
|
||||
disi := isv1.DeleteSnapshotInput{
|
||||
SnapshotID: req.SnapshotID,
|
||||
ItemFromBackup: &itemFromBackup,
|
||||
SnapshotMetadata: req.Metadata,
|
||||
Params: req.Params,
|
||||
}
|
||||
|
||||
err = impl.DeleteSnapshot(ctx, &disi)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (recv *ItemSnapshotterGRPCServer) CreateItemFromSnapshot(ctx context.Context, req *proto.CreateItemFromSnapshotRequest) (res *proto.CreateItemFromSnapshotResponse, err error) {
|
||||
defer func() {
|
||||
if recoveredErr := handlePanic(recover()); recoveredErr != nil {
|
||||
err = recoveredErr
|
||||
}
|
||||
}()
|
||||
impl, err := recv.getImpl(req.Plugin)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
var snapshottedItem unstructured.Unstructured
|
||||
if err := json.Unmarshal(req.Item, &snapshottedItem); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
|
||||
var itemFromBackup unstructured.Unstructured
|
||||
if err := json.Unmarshal(req.Item, &itemFromBackup); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
|
||||
var restore api.Restore
|
||||
|
||||
if err := json.Unmarshal(req.Restore, &restore); err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
|
||||
cii := isv1.CreateItemInput{
|
||||
SnapshottedItem: &snapshottedItem,
|
||||
SnapshotID: req.SnapshotID,
|
||||
ItemFromBackup: &itemFromBackup,
|
||||
SnapshotMetadata: req.SnapshotMetadata,
|
||||
Params: req.Params,
|
||||
Restore: &restore,
|
||||
}
|
||||
|
||||
cio, err := impl.CreateItemFromSnapshot(ctx, &cii)
|
||||
if err != nil {
|
||||
return nil, newGRPCError(err)
|
||||
}
|
||||
|
||||
var updatedItemJSON []byte
|
||||
if cio.UpdatedItem == nil {
|
||||
updatedItemJSON = req.Item
|
||||
} else {
|
||||
updatedItemJSON, err = json.Marshal(cio.UpdatedItem.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, newGRPCError(errors.WithStack(err))
|
||||
}
|
||||
}
|
||||
res = &proto.CreateItemFromSnapshotResponse{
|
||||
Item: updatedItemJSON,
|
||||
SkipRestore: cio.SkipRestore,
|
||||
}
|
||||
res.AdditionalItems = packResourceIdentifiers(cio.AdditionalItems)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -41,6 +41,9 @@ const (
|
||||
// PluginKindDeleteItemAction represents a delete item action plugin.
|
||||
PluginKindDeleteItemAction PluginKind = "DeleteItemAction"
|
||||
|
||||
// PluginKindItemSnapshotter represents an item snapshotter plugin
|
||||
PluginKindItemSnapshotter PluginKind = "ItemSnapshotter"
|
||||
|
||||
// PluginKindPluginLister represents a plugin lister plugin.
|
||||
PluginKindPluginLister PluginKind = "PluginLister"
|
||||
)
|
||||
@@ -54,5 +57,6 @@ func AllPluginKinds() map[string]PluginKind {
|
||||
allPluginKinds[PluginKindBackupItemAction.String()] = PluginKindBackupItemAction
|
||||
allPluginKinds[PluginKindRestoreItemAction.String()] = PluginKindRestoreItemAction
|
||||
allPluginKinds[PluginKindDeleteItemAction.String()] = PluginKindDeleteItemAction
|
||||
allPluginKinds[PluginKindItemSnapshotter.String()] = PluginKindItemSnapshotter
|
||||
return allPluginKinds
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ func TestPluginImplementationsAreGRPCPlugins(t *testing.T) {
|
||||
new(ObjectStorePlugin),
|
||||
new(PluginListerPlugin),
|
||||
new(RestoreItemActionPlugin),
|
||||
new(ItemSnapshotterPlugin),
|
||||
}
|
||||
|
||||
for _, impl := range pluginImpls {
|
||||
|
||||
58
pkg/plugin/framework/util.go
Normal file
58
pkg/plugin/framework/util.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package framework
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
func packResourceIdentifiers(resourcesIDs []velero.ResourceIdentifier) (protoIDs []*proto.ResourceIdentifier) {
|
||||
for _, item := range resourcesIDs {
|
||||
protoIDs = append(protoIDs, resourceIdentifierToProto(item))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func unpackResourceIdentifiers(protoIDs []*proto.ResourceIdentifier) (resourceIDs []velero.ResourceIdentifier) {
|
||||
for _, itm := range protoIDs {
|
||||
resourceIDs = append(resourceIDs, protoToResourceIdentifier(itm))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func protoToResourceIdentifier(proto *proto.ResourceIdentifier) velero.ResourceIdentifier {
|
||||
return velero.ResourceIdentifier{
|
||||
GroupResource: schema.GroupResource{
|
||||
Group: proto.Group,
|
||||
Resource: proto.Resource,
|
||||
},
|
||||
Namespace: proto.Namespace,
|
||||
Name: proto.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func resourceIdentifierToProto(id velero.ResourceIdentifier) *proto.ResourceIdentifier {
|
||||
return &proto.ResourceIdentifier{
|
||||
Group: id.Group,
|
||||
Resource: id.Resource,
|
||||
Namespace: id.Namespace,
|
||||
Name: id.Name,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user