Skip to content

Commit

Permalink
Merge pull request #8054 from sseago/iba-plugins
Browse files Browse the repository at this point in the history
Iba plugins
  • Loading branch information
Lyndon-Li authored Aug 15, 2024
2 parents 4e781d4 + 1228b41 commit 8fde4a0
Show file tree
Hide file tree
Showing 16 changed files with 1,460 additions and 147 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/8054-sseago
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Internal ItemBlockAction plugins
10 changes: 3 additions & 7 deletions pkg/backup/actions/backup_pv_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"

v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/kuberesource"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
"github.com/vmware-tanzu/velero/pkg/util/actionhelpers"
)

// PVCAction inspects a PersistentVolumeClaim for the PersistentVolume
Expand All @@ -51,7 +51,7 @@ func (a *PVCAction) AppliesTo() (velero.ResourceSelector, error) {
func (a *PVCAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
a.log.Info("Executing PVCAction")

var pvc corev1api.PersistentVolumeClaim
pvc := new(corev1api.PersistentVolumeClaim)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(item.UnstructuredContent(), &pvc); err != nil {
return nil, nil, errors.Wrap(err, "unable to convert unstructured item to persistent volume claim")
}
Expand All @@ -60,10 +60,6 @@ func (a *PVCAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runti
return item, nil, nil
}

pv := velero.ResourceIdentifier{
GroupResource: kuberesource.PersistentVolumes,
Name: pvc.Spec.VolumeName,
}
// remove dataSource if exists from prior restored CSI volumes
if pvc.Spec.DataSource != nil {
pvc.Spec.DataSource = nil
Expand Down Expand Up @@ -94,5 +90,5 @@ func (a *PVCAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runti
return nil, nil, errors.Wrap(err, "unable to convert pvc to unstructured item")
}

return &unstructured.Unstructured{Object: pvcMap}, []velero.ResourceIdentifier{pv}, nil
return &unstructured.Unstructured{Object: pvcMap}, actionhelpers.RelatedItemsForPVC(pvc, a.log), nil
}
31 changes: 2 additions & 29 deletions pkg/backup/actions/pod_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"

v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/kuberesource"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
"github.com/vmware-tanzu/velero/pkg/util/actionhelpers"
)

// PodAction implements ItemAction.
Expand Down Expand Up @@ -55,32 +55,5 @@ func (a *PodAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runti
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(item.UnstructuredContent(), pod); err != nil {
return nil, nil, errors.WithStack(err)
}

var additionalItems []velero.ResourceIdentifier
if pod.Spec.PriorityClassName != "" {
a.log.Infof("Adding priorityclass %s to additionalItems", pod.Spec.PriorityClassName)
additionalItems = append(additionalItems, velero.ResourceIdentifier{
GroupResource: kuberesource.PriorityClasses,
Name: pod.Spec.PriorityClassName,
})
}

if len(pod.Spec.Volumes) == 0 {
a.log.Info("pod has no volumes")
return item, additionalItems, nil
}

for _, volume := range pod.Spec.Volumes {
if volume.PersistentVolumeClaim != nil && volume.PersistentVolumeClaim.ClaimName != "" {
a.log.Infof("Adding pvc %s to additionalItems", volume.PersistentVolumeClaim.ClaimName)

additionalItems = append(additionalItems, velero.ResourceIdentifier{
GroupResource: kuberesource.PersistentVolumeClaims,
Namespace: pod.Namespace,
Name: volume.PersistentVolumeClaim.ClaimName,
})
}
}

return item, additionalItems, nil
return item, actionhelpers.RelatedItemsForPod(pod, a.log), nil
}
61 changes: 5 additions & 56 deletions pkg/backup/actions/service_account_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,24 @@ package actions
import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"

v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery"
"github.com/vmware-tanzu/velero/pkg/kuberesource"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
"github.com/vmware-tanzu/velero/pkg/util/actionhelpers"
)

// ServiceAccountAction implements ItemAction.
type ServiceAccountAction struct {
log logrus.FieldLogger
clusterRoleBindings []ClusterRoleBinding
clusterRoleBindings []actionhelpers.ClusterRoleBinding
}

// NewServiceAccountAction creates a new ItemAction for service accounts.
func NewServiceAccountAction(logger logrus.FieldLogger, clusterRoleBindingListers map[string]ClusterRoleBindingLister, discoveryHelper velerodiscovery.Helper) (*ServiceAccountAction, error) {
// Look up the supported RBAC version
var supportedAPI metav1.GroupVersionForDiscovery
for _, ag := range discoveryHelper.APIGroups() {
if ag.Name == rbac.GroupName {
supportedAPI = ag.PreferredVersion
break
}
}

crbLister := clusterRoleBindingListers[supportedAPI.Version]

// This should be safe because the List call will return a 0-item slice
// if there's no matching API version.
crbs, err := crbLister.List()
func NewServiceAccountAction(logger logrus.FieldLogger, clusterRoleBindingListers map[string]actionhelpers.ClusterRoleBindingLister, discoveryHelper velerodiscovery.Helper) (*ServiceAccountAction, error) {
crbs, err := actionhelpers.ClusterRoleBindingsForAction(clusterRoleBindingListers, discoveryHelper)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -82,40 +66,5 @@ func (a *ServiceAccountAction) Execute(item runtime.Unstructured, backup *v1.Bac
return nil, nil, errors.WithStack(err)
}

var (
namespace = objectMeta.GetNamespace()
name = objectMeta.GetName()
bindings = sets.NewString()
roles = sets.NewString()
)

for _, crb := range a.clusterRoleBindings {
for _, s := range crb.ServiceAccountSubjects(namespace) {
if s == name {
a.log.Infof("Adding clusterrole %s and clusterrolebinding %s to additionalItems since serviceaccount %s/%s is a subject",
crb.RoleRefName(), crb.Name(), namespace, name)

bindings.Insert(crb.Name())
roles.Insert(crb.RoleRefName())
break
}
}
}

var additionalItems []velero.ResourceIdentifier
for binding := range bindings {
additionalItems = append(additionalItems, velero.ResourceIdentifier{
GroupResource: kuberesource.ClusterRoleBindings,
Name: binding,
})
}

for role := range roles {
additionalItems = append(additionalItems, velero.ResourceIdentifier{
GroupResource: kuberesource.ClusterRoles,
Name: role,
})
}

return item, additionalItems, nil
return item, actionhelpers.RelatedItemsForServiceAccount(objectMeta, a.clusterRoleBindings, a.log), nil
}
53 changes: 27 additions & 26 deletions pkg/backup/actions/service_account_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,22 @@ import (
"github.com/vmware-tanzu/velero/pkg/kuberesource"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
velerotest "github.com/vmware-tanzu/velero/pkg/test"
"github.com/vmware-tanzu/velero/pkg/util/actionhelpers"
)

func newV1ClusterRoleBindingList(rbacCRBList []rbac.ClusterRoleBinding) []ClusterRoleBinding {
var crbs []ClusterRoleBinding
func newV1ClusterRoleBindingList(rbacCRBList []rbac.ClusterRoleBinding) []actionhelpers.ClusterRoleBinding {
var crbs []actionhelpers.ClusterRoleBinding
for _, c := range rbacCRBList {
crbs = append(crbs, v1ClusterRoleBinding{crb: c})
crbs = append(crbs, actionhelpers.V1ClusterRoleBinding{Crb: c})
}

return crbs
}

func newV1beta1ClusterRoleBindingList(rbacCRBList []rbacbeta.ClusterRoleBinding) []ClusterRoleBinding {
var crbs []ClusterRoleBinding
func newV1beta1ClusterRoleBindingList(rbacCRBList []rbacbeta.ClusterRoleBinding) []actionhelpers.ClusterRoleBinding {
var crbs []actionhelpers.ClusterRoleBinding
for _, c := range rbacCRBList {
crbs = append(crbs, v1beta1ClusterRoleBinding{crb: c})
crbs = append(crbs, actionhelpers.V1beta1ClusterRoleBinding{Crb: c})
}

return crbs
Expand All @@ -55,10 +56,10 @@ type FakeV1ClusterRoleBindingLister struct {
v1crbs []rbac.ClusterRoleBinding
}

func (f FakeV1ClusterRoleBindingLister) List() ([]ClusterRoleBinding, error) {
var crbs []ClusterRoleBinding
func (f FakeV1ClusterRoleBindingLister) List() ([]actionhelpers.ClusterRoleBinding, error) {
var crbs []actionhelpers.ClusterRoleBinding
for _, c := range f.v1crbs {
crbs = append(crbs, v1ClusterRoleBinding{crb: c})
crbs = append(crbs, actionhelpers.V1ClusterRoleBinding{Crb: c})
}
return crbs, nil
}
Expand All @@ -67,10 +68,10 @@ type FakeV1beta1ClusterRoleBindingLister struct {
v1beta1crbs []rbacbeta.ClusterRoleBinding
}

func (f FakeV1beta1ClusterRoleBindingLister) List() ([]ClusterRoleBinding, error) {
var crbs []ClusterRoleBinding
func (f FakeV1beta1ClusterRoleBindingLister) List() ([]actionhelpers.ClusterRoleBinding, error) {
var crbs []actionhelpers.ClusterRoleBinding
for _, c := range f.v1beta1crbs {
crbs = append(crbs, v1beta1ClusterRoleBinding{crb: c})
crbs = append(crbs, actionhelpers.V1beta1ClusterRoleBinding{Crb: c})
}
return crbs, nil
}
Expand All @@ -93,21 +94,21 @@ func TestNewServiceAccountAction(t *testing.T) {
tests := []struct {
name string
version string
expectedCRBs []ClusterRoleBinding
expectedCRBs []actionhelpers.ClusterRoleBinding
}{
{
name: "rbac v1 API instantiates an saAction",
version: rbac.SchemeGroupVersion.Version,
expectedCRBs: []ClusterRoleBinding{
v1ClusterRoleBinding{
crb: rbac.ClusterRoleBinding{
expectedCRBs: []actionhelpers.ClusterRoleBinding{
actionhelpers.V1ClusterRoleBinding{
Crb: rbac.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "v1crb-1",
},
},
},
v1ClusterRoleBinding{
crb: rbac.ClusterRoleBinding{
actionhelpers.V1ClusterRoleBinding{
Crb: rbac.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "v1crb-2",
},
Expand All @@ -118,16 +119,16 @@ func TestNewServiceAccountAction(t *testing.T) {
{
name: "rbac v1beta1 API instantiates an saAction",
version: rbacbeta.SchemeGroupVersion.Version,
expectedCRBs: []ClusterRoleBinding{
v1beta1ClusterRoleBinding{
crb: rbacbeta.ClusterRoleBinding{
expectedCRBs: []actionhelpers.ClusterRoleBinding{
actionhelpers.V1beta1ClusterRoleBinding{
Crb: rbacbeta.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "v1beta1crb-1",
},
},
},
v1beta1ClusterRoleBinding{
crb: rbacbeta.ClusterRoleBinding{
actionhelpers.V1beta1ClusterRoleBinding{
Crb: rbacbeta.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "v1beta1crb-2",
},
Expand All @@ -138,7 +139,7 @@ func TestNewServiceAccountAction(t *testing.T) {
{
name: "no RBAC API instantiates an saAction with empty slice",
version: "",
expectedCRBs: []ClusterRoleBinding{},
expectedCRBs: []actionhelpers.ClusterRoleBinding{},
},
}
// Set up all of our fakes outside the test loop
Expand Down Expand Up @@ -171,10 +172,10 @@ func TestNewServiceAccountAction(t *testing.T) {
},
}

clusterRoleBindingListers := map[string]ClusterRoleBindingLister{
clusterRoleBindingListers := map[string]actionhelpers.ClusterRoleBindingLister{
rbac.SchemeGroupVersion.Version: FakeV1ClusterRoleBindingLister{v1crbs: v1crbs},
rbacbeta.SchemeGroupVersion.Version: FakeV1beta1ClusterRoleBindingLister{v1beta1crbs: v1beta1crbs},
"": noopClusterRoleBindingLister{},
"": actionhelpers.NoopClusterRoleBindingLister{},
}

for _, test := range tests {
Expand Down
51 changes: 50 additions & 1 deletion pkg/cmd/server/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ import (
"github.com/vmware-tanzu/velero/pkg/client"
velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery"
"github.com/vmware-tanzu/velero/pkg/features"
iba "github.com/vmware-tanzu/velero/pkg/itemblock/actions"
veleroplugin "github.com/vmware-tanzu/velero/pkg/plugin/framework"
plugincommon "github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
ria "github.com/vmware-tanzu/velero/pkg/restore/actions"
csiria "github.com/vmware-tanzu/velero/pkg/restore/actions/csi"
"github.com/vmware-tanzu/velero/pkg/util/actionhelpers"
)

func NewCommand(f client.Factory) *cobra.Command {
Expand Down Expand Up @@ -171,6 +173,18 @@ func NewCommand(f client.Factory) *cobra.Command {
RegisterRestoreItemActionV2(
"velero.io/csi-volumesnapshotclass-restorer",
newVolumeSnapshotClassRestoreItemAction,
).
RegisterItemBlockAction(
"velero.io/pvc",
newPVCItemBlockAction(f),
).
RegisterItemBlockAction(
"velero.io/pod",
newPodItemBlockAction,
).
RegisterItemBlockAction(
"velero.io/service-account",
newServiceAccountItemBlockAction(f),
)

if !features.IsEnabled(velerov1api.APIGroupVersionsFeatureFlag) {
Expand Down Expand Up @@ -211,7 +225,7 @@ func newServiceAccountBackupItemAction(f client.Factory) plugincommon.HandlerIni

action, err := bia.NewServiceAccountAction(
logger,
bia.NewClusterRoleBindingListerMap(clientset),
actionhelpers.NewClusterRoleBindingListerMap(clientset),
discoveryHelper)
if err != nil {
return nil, err
Expand Down Expand Up @@ -431,3 +445,38 @@ func newVolumeSnapshotContentRestoreItemAction(logger logrus.FieldLogger) (inter
func newVolumeSnapshotClassRestoreItemAction(logger logrus.FieldLogger) (interface{}, error) {
return csiria.NewVolumeSnapshotClassRestoreItemAction(logger)
}

// ItemBlockAction plugins

func newPVCItemBlockAction(f client.Factory) plugincommon.HandlerInitializer {
return iba.NewPVCAction(f)
}

func newPodItemBlockAction(logger logrus.FieldLogger) (interface{}, error) {
return iba.NewPodAction(logger), nil
}

func newServiceAccountItemBlockAction(f client.Factory) plugincommon.HandlerInitializer {
return func(logger logrus.FieldLogger) (interface{}, error) {
// TODO(ncdc): consider a k8s style WantsKubernetesClientSet initialization approach
clientset, err := f.KubeClient()
if err != nil {
return nil, err
}

discoveryHelper, err := velerodiscovery.NewHelper(clientset.Discovery(), logger)
if err != nil {
return nil, err
}

action, err := iba.NewServiceAccountAction(
logger,
actionhelpers.NewClusterRoleBindingListerMap(clientset),
discoveryHelper)
if err != nil {
return nil, err
}

return action, nil
}
}
Loading

0 comments on commit 8fde4a0

Please sign in to comment.