New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kubevirt: simplify wrapper classes #4321
kubevirt: simplify wrapper classes #4321
Conversation
export class MutableDiskWrapper extends DiskWrapper { | ||
public constructor(disk?: V1Disk, copy = false) { | ||
super(disk, { copy }); | ||
protected sanitize(type: DiskType, { bus }: CombinedTypeData) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each wrapper should implement its own sanitize function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each wrapper should implement its own sanitize function
In case each wrapper's sanitize
will be different in some (wrapper-specific) way, maybe we should make it an abstract
method - assuming we'd never want to use the fallback "clone deep" implementation for any of the wrappers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would keep for now
- we can default to it in the child class
- could be used by a type which would have the same attributes for each instance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, let's keep it for now.
const type = this.getType(); | ||
this.setType(type, { ...this.getTypeData(type), ...newTypeData }); | ||
}; | ||
public appendType = (type?: TYPE, newTypeData?: COMBINED_TYPE_DATA, sanitize = true) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which will be used by default when changing the typeData
new DiskWrapper({ | ||
name, | ||
bootOrder, | ||
}).setType(type, { bus: bus?.getValue() }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
used every time when intializing data from UI
return (this as any) as SELF; | ||
}; | ||
|
||
setName = (name: string) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
K8sResourceObjectWithTypePropertyWrapper
and K8sResourceWrapper
cannot be united so we have to duplicate code here. But it should be in only these two places and the duplicated logic is pretty simple
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Class hierarchies impose limits on reusability from inheritance perspective.
The closest common ancestor of K8sResourceWrapper
and K8sResourceObjectWithTypePropertyWrapper
is Wrapper
. But IIUC it doesn't make sense to put these methods into Wrapper
.
One way to reuse duplicated code here would be the concept of mixins. (Not a big deal if the logic is simple enough.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, let's keep this in mind and take care of it if the logic becomes too advanced or diverges in the future
398a66f
to
0e84122
Compare
/retest |
1 similar comment
/retest |
const diskWrapper = DiskWrapper.initialize(disk); | ||
const volumeWrapper = VolumeWrapper.initialize(volume); | ||
const dataVolumeWrapper = dataVolume && new MutableDataVolumeWrapper(dataVolume, true); | ||
const diskWrapper = new DiskWrapper(disk); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i like this syntax 🎉
@@ -26,15 +26,15 @@ export const prefillInitialDiskUpdater = ({ id, prevState, dispatch, getState }: | |||
const oldType = | |||
oldSourceStorage && | |||
StorageUISource.fromTypes( | |||
VolumeWrapper.initialize(oldSourceStorage.volume).getType(), | |||
DataVolumeWrapper.initialize(oldSourceStorage.dataVolume).getType(), | |||
new VolumeWrapper(oldSourceStorage.volume).getType(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need to initiate two constructors just for types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrappers encapsulate the type mapping which can be described by any part of the object. So far, it is necessary.
StorageUISource is the mapping of the types for our final custom UI type
volume={new VolumeWrapper(volumeWrapper, true)} | ||
dataVolume={dataVolumeWrapper && new DataVolumeWrapper(dataVolumeWrapper, true)} | ||
persistentVolumeClaim={ | ||
persistentVolumeClaimWrapper && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we move this safety to the constructor somehow? (applicable to all constructors)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really, because we need to preserve the information that the value is missing entirely and not just that the value is not filled (datavolume object exists).
I already tried that with empty objects and it was causing more problems than it solved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also creates an expectation that some wrappers might be falsy (undefined) so code working with them needs to keep that in mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, the code does
@@ -58,7 +58,7 @@ const getVirtualStoragesData = ( | |||
volumeWrapper, | |||
dataVolumeWrapper, | |||
persistentVolumeClaimWrapper: | |||
persistentVolumeClaimWrapper || (pvc && PersistentVolumeClaimWrapper.initialize(pvc)), | |||
persistentVolumeClaimWrapper || (pvc && new PersistentVolumeClaimWrapper(pvc)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same safety comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0e84122
to
3db7052
Compare
rebased |
/remove-label needs-rebase |
@suomiy: The label(s) In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
3db7052
to
c50ec9d
Compare
if (type === VolumeType.DATA_VOLUME) { | ||
return { name }; | ||
} | ||
if (type === VolumeType.PERSISTENT_VOLUME_CLAIM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a particular reason there's no space between these two conditionals? If not, could you please add one for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! this made me realize that switch statements are better choice
switch (type) { | ||
case DataVolumeSourceType.HTTP: | ||
return { url }; | ||
case DataVolumeSourceType.PVC: | ||
return { name, namespace }; | ||
case DataVolumeSourceType.BLANK: | ||
default: | ||
return {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 - I definitely prefer the switch statements over multiple ifs in this situation.
@@ -3,53 +3,33 @@ import { V1Disk } from '../../../types/vm/disk/V1Disk'; | |||
import { DiskType, DiskBus } from '../../../constants/vm/storage'; | |||
|
|||
type CombinedTypeData = { | |||
bus?: DiskBus; | |||
bus?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, but why did you drop to a less specific type here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because we use the raw data in the internal structure of the Wrapper which is string. The handling of the CombinedTypeData and sanitize function were moved to the baseClass. The DiskWrapper can still expose the bus as DiskBus enum in the getter
/lgtm |
eb8ef94
to
2bf924b
Compare
0674eb6
to
97643aa
Compare
/hold cancel |
fixed |
- unify mutable and immutable constructors - make constructors easier to use - make copy on costruct and asResource more permissive - remove unnecesary mergeWrappers - deprecate asMutableResource and replace with asResource
- deprecate initiliaze functions in favor of new keyword - deprecate storage mutable wrappers - create K8sResourceObjectWithTypePropertyWrapper for multiple inheritance - make constructors easier to use - make copy on costruct and asResource more permissive - deprecate asMutableResource and replace with asResource
…meClaimWrapper - deprecate inner usage of EMPTY objects
- deprecate defaultMergeWrappersWithType as all entities should use mergeWith - simplify initializeFromSimpleData - enhance ObjectWithTypePropertyWrapper and move setters and sanitize functionality there - each wrapper implements its own sanitize function - smiplify constructors and deprecate initializeWithType - constructor can copy wrapper
- remove unnecessary public modifiers
97643aa
to
68708dd
Compare
rebased |
/retest |
1 similar comment
/retest |
@suomiy Were there any effective changes added recently, or is it just a rebase? |
OK, I see there's an extra commit 68708dd - ack 😃 |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: pcbailey, suomiy, vojtechszocs The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/retest |
@suomiy: The following test failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
/retest |
I tried to move most of the duplicate logic to the parent classes and simplify the usage of the wrappers so it is less confusing.
Please let me know, what else would you fix, or name differently.
PS look into commit messages for details.
@vojtechszocs @irosenzw @glekner @pcbailey @mareklibra
@rawagner @yaacov