mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-01-04 20:24:02 +00:00
Refactors the framework package to implement the plugin versioning changes needed for BIA v1 and overall package refactoring to support plugin versions in different packages. This should be all that's needed to move on to v2 for BackupItemAction. The remaining plugin types still need similar refactoring to what's being done here for BIA before attempting a v2 implementation. Signed-off-by: Scott Seago <sseago@redhat.com>
243 lines
7.9 KiB
Go
243 lines
7.9 KiB
Go
/*
|
|
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 (
|
|
"github.com/sirupsen/logrus"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
|
|
"github.com/vmware-tanzu/velero/pkg/discovery"
|
|
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
|
biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1"
|
|
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
|
|
"github.com/vmware-tanzu/velero/pkg/util/collections"
|
|
)
|
|
|
|
/*
|
|
Velero has a variety of Actions that can be executed on Kubernetes resources. The Actions (BackupItemAction, RestoreItemAction
|
|
and others) implement the Applicable interface which returns a ResourceSelector for the Action. The ResourceSelector
|
|
can specify namespaces, resource names and labels to include or exclude. The ResourceSelector is resolved into lists
|
|
of namespaces and resources present in the backup to be matched against. These lists and the label selector are then used to
|
|
decide whether or not the ResolvedAction should be used for a particular resource.
|
|
*/
|
|
|
|
// ResolvedAction is an action that has had the namespaces, resources names and labels to include or exclude resolved
|
|
type ResolvedAction interface {
|
|
// ShouldUse returns true if the resolved namespaces, resource names and labels match those passed in the parameters.
|
|
// metadata is optional and may be nil
|
|
ShouldUse(groupResource schema.GroupResource, namespace string, metadata metav1.Object,
|
|
log logrus.FieldLogger) bool
|
|
}
|
|
|
|
// resolvedAction is a core struct that holds the resolved namespaces, resource names and labels
|
|
type resolvedAction struct {
|
|
ResourceIncludesExcludes *collections.IncludesExcludes
|
|
NamespaceIncludesExcludes *collections.IncludesExcludes
|
|
Selector labels.Selector
|
|
}
|
|
|
|
func (recv resolvedAction) ShouldUse(groupResource schema.GroupResource, namespace string, metadata metav1.Object,
|
|
log logrus.FieldLogger) bool {
|
|
if !recv.ResourceIncludesExcludes.ShouldInclude(groupResource.String()) {
|
|
log.Debug("Skipping action because it does not apply to this resource")
|
|
return false
|
|
}
|
|
|
|
if namespace != "" && !recv.NamespaceIncludesExcludes.ShouldInclude(namespace) {
|
|
log.Debug("Skipping action because it does not apply to this namespace")
|
|
return false
|
|
}
|
|
|
|
if namespace == "" && !recv.NamespaceIncludesExcludes.IncludeEverything() {
|
|
log.Debug("Skipping action because resource is cluster-scoped and action only applies to specific namespaces")
|
|
return false
|
|
}
|
|
|
|
if metadata != nil && !recv.Selector.Matches(labels.Set(metadata.GetLabels())) {
|
|
log.Debug("Skipping action because label selector does not match")
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// resolveAction resolves the resources, namespaces and selector into fully-qualified versions
|
|
func resolveAction(helper discovery.Helper, action velero.Applicable) (resources *collections.IncludesExcludes,
|
|
namespaces *collections.IncludesExcludes, selector labels.Selector, err error) {
|
|
resourceSelector, err := action.AppliesTo()
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
resources = collections.GetResourceIncludesExcludes(helper, resourceSelector.IncludedResources, resourceSelector.ExcludedResources)
|
|
namespaces = collections.NewIncludesExcludes().Includes(resourceSelector.IncludedNamespaces...).Excludes(resourceSelector.ExcludedNamespaces...)
|
|
|
|
selector = labels.Everything()
|
|
if resourceSelector.LabelSelector != "" {
|
|
if selector, err = labels.Parse(resourceSelector.LabelSelector); err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
type BackupItemResolvedAction struct {
|
|
biav1.BackupItemAction
|
|
resolvedAction
|
|
}
|
|
|
|
func NewBackupItemActionResolver(actions []biav1.BackupItemAction) BackupItemActionResolver {
|
|
return BackupItemActionResolver{
|
|
actions: actions,
|
|
}
|
|
}
|
|
|
|
func NewRestoreItemActionResolver(actions []velero.RestoreItemAction) RestoreItemActionResolver {
|
|
return RestoreItemActionResolver{
|
|
actions: actions,
|
|
}
|
|
}
|
|
|
|
func NewDeleteItemActionResolver(actions []velero.DeleteItemAction) DeleteItemActionResolver {
|
|
return DeleteItemActionResolver{
|
|
actions: actions,
|
|
}
|
|
}
|
|
|
|
func NewItemSnapshotterResolver(actions []isv1.ItemSnapshotter) ItemSnapshotterResolver {
|
|
return ItemSnapshotterResolver{
|
|
actions: actions,
|
|
}
|
|
}
|
|
|
|
type ActionResolver interface {
|
|
ResolveAction(helper discovery.Helper, action velero.Applicable, log logrus.FieldLogger) (ResolvedAction, error)
|
|
}
|
|
|
|
type BackupItemActionResolver struct {
|
|
actions []biav1.BackupItemAction
|
|
}
|
|
|
|
func (recv BackupItemActionResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]BackupItemResolvedAction, error) {
|
|
var resolved []BackupItemResolvedAction
|
|
for _, action := range recv.actions {
|
|
resources, namespaces, selector, err := resolveAction(helper, action)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res := BackupItemResolvedAction{
|
|
BackupItemAction: action,
|
|
resolvedAction: resolvedAction{
|
|
ResourceIncludesExcludes: resources,
|
|
NamespaceIncludesExcludes: namespaces,
|
|
Selector: selector,
|
|
},
|
|
}
|
|
resolved = append(resolved, res)
|
|
}
|
|
return resolved, nil
|
|
}
|
|
|
|
type RestoreItemResolvedAction struct {
|
|
velero.RestoreItemAction
|
|
resolvedAction
|
|
}
|
|
|
|
type RestoreItemActionResolver struct {
|
|
actions []velero.RestoreItemAction
|
|
}
|
|
|
|
func (recv RestoreItemActionResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]RestoreItemResolvedAction, error) {
|
|
var resolved []RestoreItemResolvedAction
|
|
for _, action := range recv.actions {
|
|
resources, namespaces, selector, err := resolveAction(helper, action)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res := RestoreItemResolvedAction{
|
|
RestoreItemAction: action,
|
|
resolvedAction: resolvedAction{
|
|
ResourceIncludesExcludes: resources,
|
|
NamespaceIncludesExcludes: namespaces,
|
|
Selector: selector,
|
|
},
|
|
}
|
|
resolved = append(resolved, res)
|
|
}
|
|
return resolved, nil
|
|
}
|
|
|
|
type DeleteItemResolvedAction struct {
|
|
velero.DeleteItemAction
|
|
resolvedAction
|
|
}
|
|
|
|
type DeleteItemActionResolver struct {
|
|
actions []velero.DeleteItemAction
|
|
}
|
|
|
|
func (recv DeleteItemActionResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]DeleteItemResolvedAction, error) {
|
|
var resolved []DeleteItemResolvedAction
|
|
for _, action := range recv.actions {
|
|
resources, namespaces, selector, err := resolveAction(helper, action)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res := DeleteItemResolvedAction{
|
|
DeleteItemAction: action,
|
|
resolvedAction: resolvedAction{
|
|
ResourceIncludesExcludes: resources,
|
|
NamespaceIncludesExcludes: namespaces,
|
|
Selector: selector,
|
|
},
|
|
}
|
|
resolved = append(resolved, res)
|
|
}
|
|
return resolved, nil
|
|
}
|
|
|
|
type ItemSnapshotterResolvedAction struct {
|
|
isv1.ItemSnapshotter
|
|
resolvedAction
|
|
}
|
|
|
|
type ItemSnapshotterResolver struct {
|
|
actions []isv1.ItemSnapshotter
|
|
}
|
|
|
|
func (recv ItemSnapshotterResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]ItemSnapshotterResolvedAction, error) {
|
|
var resolved []ItemSnapshotterResolvedAction
|
|
for _, action := range recv.actions {
|
|
resources, namespaces, selector, err := resolveAction(helper, action)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res := ItemSnapshotterResolvedAction{
|
|
ItemSnapshotter: action,
|
|
resolvedAction: resolvedAction{
|
|
ResourceIncludesExcludes: resources,
|
|
NamespaceIncludesExcludes: namespaces,
|
|
Selector: selector,
|
|
},
|
|
}
|
|
resolved = append(resolved, res)
|
|
}
|
|
return resolved, nil
|
|
}
|