-
Notifications
You must be signed in to change notification settings - Fork 150
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(v2 upgrade/webhook): validate data engine upgrade related fields
Longhorn 9104 Signed-off-by: Derek Su <[email protected]>
- Loading branch information
Showing
8 changed files
with
465 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package dataengineupgrademanager | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"k8s.io/apimachinery/pkg/runtime" | ||
|
||
admissionregv1 "k8s.io/api/admissionregistration/v1" | ||
|
||
"github.com/longhorn/longhorn-manager/datastore" | ||
"github.com/longhorn/longhorn-manager/types" | ||
"github.com/longhorn/longhorn-manager/webhook/admission" | ||
"github.com/longhorn/longhorn-manager/webhook/common" | ||
|
||
longhorn "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2" | ||
werror "github.com/longhorn/longhorn-manager/webhook/error" | ||
) | ||
|
||
type dataEngineUpgradeManagerMutator struct { | ||
admission.DefaultMutator | ||
ds *datastore.DataStore | ||
} | ||
|
||
func NewMutator(ds *datastore.DataStore) admission.Mutator { | ||
return &dataEngineUpgradeManagerMutator{ds: ds} | ||
} | ||
|
||
func (u *dataEngineUpgradeManagerMutator) Resource() admission.Resource { | ||
return admission.Resource{ | ||
Name: "dataengineupgrademanagers", | ||
Scope: admissionregv1.NamespacedScope, | ||
APIGroup: longhorn.SchemeGroupVersion.Group, | ||
APIVersion: longhorn.SchemeGroupVersion.Version, | ||
ObjectType: &longhorn.DataEngineUpgradeManager{}, | ||
OperationTypes: []admissionregv1.OperationType{ | ||
admissionregv1.Create, | ||
}, | ||
} | ||
} | ||
|
||
func (u *dataEngineUpgradeManagerMutator) Create(request *admission.Request, newObj runtime.Object) (admission.PatchOps, error) { | ||
return mutate(newObj) | ||
} | ||
|
||
func mutate(newObj runtime.Object) (admission.PatchOps, error) { | ||
upgradeManager, ok := newObj.(*longhorn.DataEngineUpgradeManager) | ||
if !ok { | ||
return nil, werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.DataEngineUpgradeManager", newObj), "") | ||
} | ||
var patchOps admission.PatchOps | ||
|
||
longhornLabels := types.GetDataEngineUpgradeManagerLabels() | ||
patchOp, err := common.GetLonghornLabelsPatchOp(upgradeManager, longhornLabels, nil) | ||
if err != nil { | ||
err := errors.Wrapf(err, "failed to get label patch for upgradeManager %v", upgradeManager.Name) | ||
return nil, werror.NewInvalidError(err.Error(), "") | ||
} | ||
if patchOp != "" { | ||
patchOps = append(patchOps, patchOp) | ||
} | ||
|
||
patchOp, err = common.GetLonghornFinalizerPatchOpIfNeeded(upgradeManager) | ||
if err != nil { | ||
err := errors.Wrapf(err, "failed to get finalizer patch for dataEngineUpgradeManager %v", upgradeManager.Name) | ||
return nil, werror.NewInvalidError(err.Error(), "") | ||
} | ||
if patchOp != "" { | ||
patchOps = append(patchOps, patchOp) | ||
} | ||
|
||
return patchOps, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package dataengineupgrademanager | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
|
||
"k8s.io/apimachinery/pkg/runtime" | ||
|
||
admissionregv1 "k8s.io/api/admissionregistration/v1" | ||
|
||
"github.com/longhorn/longhorn-manager/datastore" | ||
"github.com/longhorn/longhorn-manager/webhook/admission" | ||
|
||
longhorn "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2" | ||
werror "github.com/longhorn/longhorn-manager/webhook/error" | ||
) | ||
|
||
type dataEngineUpgradeManagerValidator struct { | ||
admission.DefaultValidator | ||
ds *datastore.DataStore | ||
} | ||
|
||
func NewValidator(ds *datastore.DataStore) admission.Validator { | ||
return &dataEngineUpgradeManagerValidator{ds: ds} | ||
} | ||
|
||
func (u *dataEngineUpgradeManagerValidator) Resource() admission.Resource { | ||
return admission.Resource{ | ||
Name: "dataengineupgrademanagers", | ||
Scope: admissionregv1.NamespacedScope, | ||
APIGroup: longhorn.SchemeGroupVersion.Group, | ||
APIVersion: longhorn.SchemeGroupVersion.Version, | ||
ObjectType: &longhorn.DataEngineUpgradeManager{}, | ||
OperationTypes: []admissionregv1.OperationType{ | ||
admissionregv1.Create, | ||
admissionregv1.Update, | ||
}, | ||
} | ||
} | ||
|
||
func (u *dataEngineUpgradeManagerValidator) Create(request *admission.Request, newObj runtime.Object) error { | ||
upgradeManager, ok := newObj.(*longhorn.DataEngineUpgradeManager) | ||
if !ok { | ||
return werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.DataEngineUpgradeManager", newObj), "") | ||
} | ||
|
||
if upgradeManager.Spec.DataEngine != longhorn.DataEngineTypeV2 { | ||
err := fmt.Errorf("data engine %v is not supported", upgradeManager.Spec.DataEngine) | ||
return werror.NewInvalidError(err.Error(), "spec.dataEngine") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (u *dataEngineUpgradeManagerValidator) Update(request *admission.Request, oldObj runtime.Object, newObj runtime.Object) error { | ||
oldUpgradeManager, ok := oldObj.(*longhorn.DataEngineUpgradeManager) | ||
if !ok { | ||
return werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.DataEngineUpgradeManager", oldObj), "") | ||
} | ||
newUpgradeManager, ok := newObj.(*longhorn.DataEngineUpgradeManager) | ||
if !ok { | ||
return werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.DataEngineUpgradeManager", newObj), "") | ||
} | ||
|
||
if newUpgradeManager.Spec.DataEngine != longhorn.DataEngineTypeV2 { | ||
err := fmt.Errorf("data engine %v is not supported", newUpgradeManager.Spec.DataEngine) | ||
return werror.NewInvalidError(err.Error(), "spec.dataEngine") | ||
} | ||
|
||
if oldUpgradeManager.Spec.DataEngine != newUpgradeManager.Spec.DataEngine { | ||
return werror.NewInvalidError("spec.dataEngine field is immutable", "spec.dataEngine") | ||
} | ||
|
||
if !reflect.DeepEqual(oldUpgradeManager.Spec.Nodes, newUpgradeManager.Spec.Nodes) { | ||
return werror.NewInvalidError("nodes field is immutable", "spec.nodes") | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package nodedataengineupgrade | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"k8s.io/apimachinery/pkg/runtime" | ||
|
||
admissionregv1 "k8s.io/api/admissionregistration/v1" | ||
|
||
"github.com/longhorn/longhorn-manager/datastore" | ||
"github.com/longhorn/longhorn-manager/types" | ||
"github.com/longhorn/longhorn-manager/webhook/admission" | ||
"github.com/longhorn/longhorn-manager/webhook/common" | ||
|
||
longhorn "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2" | ||
werror "github.com/longhorn/longhorn-manager/webhook/error" | ||
) | ||
|
||
type nodeDataEngineUpgradeMutator struct { | ||
admission.DefaultMutator | ||
ds *datastore.DataStore | ||
} | ||
|
||
func NewMutator(ds *datastore.DataStore) admission.Mutator { | ||
return &nodeDataEngineUpgradeMutator{ds: ds} | ||
} | ||
|
||
func (u *nodeDataEngineUpgradeMutator) Resource() admission.Resource { | ||
return admission.Resource{ | ||
Name: "nodedataengineupgrades", | ||
Scope: admissionregv1.NamespacedScope, | ||
APIGroup: longhorn.SchemeGroupVersion.Group, | ||
APIVersion: longhorn.SchemeGroupVersion.Version, | ||
ObjectType: &longhorn.NodeDataEngineUpgrade{}, | ||
OperationTypes: []admissionregv1.OperationType{ | ||
admissionregv1.Create, | ||
}, | ||
} | ||
} | ||
|
||
func (u *nodeDataEngineUpgradeMutator) Create(request *admission.Request, newObj runtime.Object) (admission.PatchOps, error) { | ||
return mutate(newObj) | ||
} | ||
|
||
func mutate(newObj runtime.Object) (admission.PatchOps, error) { | ||
nodeUpgrade, ok := newObj.(*longhorn.NodeDataEngineUpgrade) | ||
if !ok { | ||
return nil, werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.NodeDataEngineUpgrade", newObj), "") | ||
} | ||
var patchOps admission.PatchOps | ||
|
||
longhornLabels := types.GetNodeDataEngineUpgradeLabels(nodeUpgrade.Spec.DataEngineUpgradeManager, nodeUpgrade.Spec.NodeID) | ||
patchOp, err := common.GetLonghornLabelsPatchOp(nodeUpgrade, longhornLabels, nil) | ||
if err != nil { | ||
err := errors.Wrapf(err, "failed to get label patch for nodeUpgrade %v", nodeUpgrade.Name) | ||
return nil, werror.NewInvalidError(err.Error(), "") | ||
} | ||
if patchOp != "" { | ||
patchOps = append(patchOps, patchOp) | ||
} | ||
|
||
patchOp, err = common.GetLonghornFinalizerPatchOpIfNeeded(nodeUpgrade) | ||
if err != nil { | ||
err := errors.Wrapf(err, "failed to get finalizer patch for nodeDataEngineUpgrade %v", nodeUpgrade.Name) | ||
return nil, werror.NewInvalidError(err.Error(), "") | ||
} | ||
if patchOp != "" { | ||
patchOps = append(patchOps, patchOp) | ||
} | ||
|
||
return patchOps, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package nodedataengineupgrade | ||
|
||
import ( | ||
"fmt" | ||
|
||
"k8s.io/apimachinery/pkg/runtime" | ||
|
||
admissionregv1 "k8s.io/api/admissionregistration/v1" | ||
|
||
"github.com/longhorn/longhorn-manager/datastore" | ||
"github.com/longhorn/longhorn-manager/webhook/admission" | ||
|
||
longhorn "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2" | ||
werror "github.com/longhorn/longhorn-manager/webhook/error" | ||
) | ||
|
||
type nodeDataEngineUpgradeValidator struct { | ||
admission.DefaultValidator | ||
ds *datastore.DataStore | ||
} | ||
|
||
func NewValidator(ds *datastore.DataStore) admission.Validator { | ||
return &nodeDataEngineUpgradeValidator{ds: ds} | ||
} | ||
|
||
func (u *nodeDataEngineUpgradeValidator) Resource() admission.Resource { | ||
return admission.Resource{ | ||
Name: "nodedataengineupgrades", | ||
Scope: admissionregv1.NamespacedScope, | ||
APIGroup: longhorn.SchemeGroupVersion.Group, | ||
APIVersion: longhorn.SchemeGroupVersion.Version, | ||
ObjectType: &longhorn.NodeDataEngineUpgrade{}, | ||
OperationTypes: []admissionregv1.OperationType{ | ||
admissionregv1.Create, | ||
admissionregv1.Update, | ||
}, | ||
} | ||
} | ||
|
||
func (u *nodeDataEngineUpgradeValidator) Create(request *admission.Request, newObj runtime.Object) error { | ||
nodeUpgrade, ok := newObj.(*longhorn.NodeDataEngineUpgrade) | ||
if !ok { | ||
return werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.NodeDataEngineUpgrade", newObj), "") | ||
} | ||
|
||
if nodeUpgrade.Spec.NodeID == "" { | ||
return werror.NewInvalidError("nodeID is required", "spec.nodeID") | ||
} | ||
|
||
if nodeUpgrade.Spec.DataEngine != longhorn.DataEngineTypeV2 { | ||
err := fmt.Errorf("data engine %v is not supported", nodeUpgrade.Spec.DataEngine) | ||
return werror.NewInvalidError(err.Error(), "spec.dataEngine") | ||
} | ||
|
||
if nodeUpgrade.Spec.InstanceManagerImage == "" { | ||
err := fmt.Errorf("instanceManagerImage is required") | ||
return werror.NewInvalidError(err.Error(), "spec.instanceManagerImage") | ||
} | ||
|
||
if nodeUpgrade.Spec.DataEngineUpgradeManager == "" { | ||
err := fmt.Errorf("dataEngineUpgradeManager is required") | ||
return werror.NewInvalidError(err.Error(), "spec.dataEngineUpgradeManager") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (u *nodeDataEngineUpgradeValidator) Update(request *admission.Request, oldObj runtime.Object, newObj runtime.Object) error { | ||
oldNodeUpgrade, ok := oldObj.(*longhorn.NodeDataEngineUpgrade) | ||
if !ok { | ||
return werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.NodeDataEngineUpgrade", oldObj), "") | ||
} | ||
newNodeUpgrade, ok := newObj.(*longhorn.NodeDataEngineUpgrade) | ||
if !ok { | ||
return werror.NewInvalidError(fmt.Sprintf("%v is not a *longhorn.NodeDataEngineUpgrade", newObj), "") | ||
} | ||
|
||
if oldNodeUpgrade.Spec.NodeID != newNodeUpgrade.Spec.NodeID { | ||
return werror.NewInvalidError("nodeID field is immutable", "spec.nodeID") | ||
} | ||
|
||
if oldNodeUpgrade.Spec.DataEngine != newNodeUpgrade.Spec.DataEngine { | ||
return werror.NewInvalidError("dataEngine field is immutable", "spec.dataEngine") | ||
} | ||
|
||
if oldNodeUpgrade.Spec.InstanceManagerImage != newNodeUpgrade.Spec.InstanceManagerImage { | ||
return werror.NewInvalidError("instanceManagerImage field is immutable", "spec.instanceManagerImage") | ||
} | ||
|
||
if oldNodeUpgrade.Spec.DataEngineUpgradeManager != newNodeUpgrade.Spec.DataEngineUpgradeManager { | ||
return werror.NewInvalidError("dataEngineUpgradeManager field is immutable", "spec.dataEngineUpgradeManager") | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.