-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[#5919] Platform: change default storage option for AWS provider to 1x250GB #6792
Conversation
[#5919] Platform: change default storage option for AWS provider to 1x250GB Description: We wanted to show default volume count to 1 on the UI for all the instance types starting with "c5./c4." Testing: When we select aws provider while creating universe, volume count was showing more than one for some instances types starting with ""c5./c4.". Now with this fix it will show only one. Will have to reset instanceTypeDetailsJson to empty for older YW instances.
Jitendra Kumar seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
@@ -44,6 +49,13 @@ | |||
NVME | |||
} | |||
|
|||
@Inject | |||
public InstanceType(ConfigFactory config) { |
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.
Config
not ConfigFactory
Like I said use TaskGarbageCollector as example.
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.
With Config, always getting NLP(Null pointers), hence used ConfigFactory instead of.
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.
Thats odd. In tests or when running server? May be some ordering issue during binding.
Inject
private final Provider<Config> config
@Inject
InstanceType(Provider config) {
...
}`
then where you use it do
config.get()
This delays the resolution to runtime.
Let me know if that fixes the problem. If not will patch and see whats wrong.
The config factory is not an option here. That code is buggy.
Another way is to get to typesafe config through play but lets try this first.
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.
Its happening while testing the code at runtime.
Getting below error:
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:
- Error injecting constructor, java.lang.NullPointerException
at AppInit.(AppInit.java:47)
at Module.configure(Module.java:48) (via modules: com.google.inject.util.Modules$OverrideModule -> Module)
while locating AppInit
Tried above things as well but that didn't work out.
Updated a patch, using config only. Please suggest! Thanks!
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.
So I saw a provider
for Config
in Module
. But looks like that is a different Config type not the typesafe.Config
.
So it is not going to work this way. Provider trick also does not delay the resolution because we need it during AppInit.
So way to do this gracefully is
- Inject
Application
inInstanceType
- Then you can get to typesafe config using
app.config()
(NOTapp.configuration()
which is deprecated)
this.config = app.config()
Let me know if that helps.
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 noticed that InstanceType is a Entity bean. So it wont use guice injection. It is using the default ctor (that you added) followed by the field mapping by the ORM and thus config remains null.
So you can just pass the config value into findByProvider as parameter. No config field.
Sorry for confusion. Right way to do this is not use so much static factory methods. Usually there is a singleton helper class like InstanceTypeHelper. That will have non-static findByProvider method. then you can actually do proper guice injection in such class.
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.
Done. Added this for now, later we will refactor the code once we have Helper method in place as you suggested above. Thanks!
@@ -29,6 +31,9 @@ | |||
|
|||
public static List<String> AWS_INSTANCE_PREFIXES_SUPPORTED = ImmutableList.of( | |||
"m3.", "c5.", "c5d.", "c4.", "c3.", "i3."); | |||
static final String YB_VOLUME_INFO_VOLUME_COUNT = "yb.volumeInfo.volume_count"; | |||
static final String YB_VOLUME_INFO_VOLUME_SIZE_GB = "yb.volumeInfo.volume_size_gb"; | |||
private static ConfigFactory config; |
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.
why static
?
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.
changed config var to non-static, others kept as it is, since those are being used in static block.
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.
yep. my comment was only about config.
for (InstanceType instanceType : entries) { | ||
if (instanceType.instanceTypeDetailsJson.isEmpty()) { | ||
instanceType.instanceTypeDetails.setVolumeDetailsList( | ||
config.load().getInt(YB_VOLUME_INFO_VOLUME_COUNT), |
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.
Inject config. Then no need to load
.
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.
done
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.
If this is the only config value then pass a parameter in to this method awsDefaultVolumeCount
Do config lookup in caller.
I will do a refactor later which should fix this DI fail as described above - using singleton helper classes.
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.
Done!
@@ -29,6 +31,9 @@ | |||
|
|||
public static List<String> AWS_INSTANCE_PREFIXES_SUPPORTED = ImmutableList.of( | |||
"m3.", "c5.", "c5d.", "c4.", "c3.", "i3."); | |||
static final String YB_VOLUME_INFO_VOLUME_COUNT = "yb.volumeInfo.volume_count"; |
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.
YB_VOLUME_INFO_VOLUME_COUNT_KEY
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.
Done.
Also bug description should say what we are doing here. |
@@ -179,6 +191,13 @@ public static void deleteInstanceTypesForProvider(Provider provider) { | |||
entries = entries.stream() | |||
.filter(supportedInstanceTypes(AWS_INSTANCE_PREFIXES_SUPPORTED)) | |||
.collect(Collectors.toList()); | |||
for (InstanceType instanceType : entries) { |
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.
extract method populateDefaultIfEmpty()
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.
done
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.
Few more changes.
@@ -13,4 +13,12 @@ yb { | |||
# For how long do we let the task be in database after it has completed | |||
task_retention_duration = 120 days | |||
} | |||
|
|||
volumeInfo { | |||
# Volume count needed for AWS instance 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.
# default volume count for aws instance types with EBS Only storage info
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.
Done
|
||
volumeInfo { | ||
# Volume count needed for AWS instance types | ||
volume_count = 1 |
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.
default_
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.
Done
volume_count = 1 | ||
|
||
# volume size in GB | ||
volume_size_gb = 250 |
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.
default_
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.
Done
@@ -13,4 +13,12 @@ yb { | |||
# For how long do we let the task be in database after it has completed | |||
task_retention_duration = 120 days | |||
} | |||
|
|||
volumeInfo { |
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.
aws { ... }
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! Done.
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.
Add unit tests
@@ -26,13 +27,20 @@ | |||
public class InstanceTypeController extends AuthenticatedController { | |||
|
|||
public static final Logger LOG = LoggerFactory.getLogger(InstanceTypeController.class); | |||
private Config config; |
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.
final
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.
done
@@ -26,13 +27,20 @@ | |||
public class InstanceTypeController extends AuthenticatedController { | |||
|
|||
public static final Logger LOG = LoggerFactory.getLogger(InstanceTypeController.class); | |||
private Config config; | |||
|
|||
@Inject | |||
FormFactory formFactory; |
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.
- Private final
- Remove Inject
- Add ctor param and assign.
@@ -26,13 +27,20 @@ | |||
public class InstanceTypeController extends AuthenticatedController { | |||
|
|||
public static final Logger LOG = LoggerFactory.getLogger(InstanceTypeController.class); | |||
private Config config; | |||
|
|||
@Inject | |||
FormFactory formFactory; | |||
|
|||
@Inject |
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.
- Private final
- Remove Inject
- Add ctor param and assign.
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.
Here we will have to use Inject, Without inject we are getting below error.
- No implementation for com.yugabyte.yw.controllers.InstanceTypeController (with no qualifier annotation) was bound, and could not find an injectable constructor. Injectable classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
@@ -185,6 +196,22 @@ public static void deleteInstanceTypesForProvider(Provider provider) { | |||
entry.getInstanceTypeCode())).collect(Collectors.toList()); | |||
} | |||
|
|||
/** |
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.
The comment is not capturing the plan correctly. Just remove the 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.
Updated the same method instead of having overloaded method.
* TODO: Please remove this method when we have helperMethod in place to get config details | ||
* Query Helper to find supported instance types for a given cloud provider. | ||
*/ | ||
public static List<InstanceType> findByProvider(Provider provider, Config config) { |
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 not make separate method. Just update same method.
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.
Updated! Thank you!
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.
@jitendra-12113 anything holding up this change? Do you need help with any part?
@sb-yb Have updated the patch. I think we are good to go ahead and merge this change. Need your approval though. Thanks! |
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.
Final lap:
small code change and missing unit test
// TODO: Remove this when we have HelperMethod in place to get Config details | ||
@Inject | ||
public InstanceTypeController(Config config) { | ||
this.config = config; |
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 not mix ctor injections and field injections in same class.
Either fix all existing fields to be parameters here or make the new field use field injection.
FWIW, using ctor injection with private fina fields is the best practice. But i ll leave it to you which option you want for now.
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.
Done. Thanks!
@@ -179,6 +190,9 @@ public static void deleteInstanceTypesForProvider(Provider provider) { | |||
entries = entries.stream() |
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.
Instead consider moving the whole code (line 190 to 196) in populateDefaultIfEmpty()
And name the method populateDefaultsIfEmpty (plural)
@@ -29,6 +31,9 @@ | |||
private Customer defaultCustomer; | |||
private InstanceType.InstanceTypeDetails defaultDetails; | |||
|
|||
@Mock |
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.
where is a test where you have to setup this mock?
when(mockConfig.get(..._COUNT)).thenReturn(1);
when(mockConfig.get(..._GB)).thenReturn(250);
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.
Ah! Didn't realise this is for entity class. We can't mock config in this file. Most of the values are being read from in memory.
Instead used ConfigFactory.load() just to test our code. I think, this should be fine if not please suggest!
Also due to static method used in Entity class, getting difficulties in writing Unit test cases, need to refactor the code(Entity class). But for now I think this should be fine.
Thanks!
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.
Given detailed instructions inline. LMK if it helps.
@@ -90,7 +94,7 @@ public void testFindByProvider() { | |||
instanceType.setActive(false); | |||
instanceType.save(); | |||
InstanceType.upsert(newProvider.code, "bar", 2, 10.0, defaultDetails); |
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 is incorrect. Not sure what is your confusion.
Here is what you have to do in great detail:
- Revert to using mock.Config
- See what is in defaultDetails - line 44 populates it. But we do not want to test that code path. To excercise our code path the defaultDetails has to be empty. Thats when the populateEmpty will do something and try to lookup config values.
- Like line 88 upsert another instancetype such that its details have volumeList empty.
- Now the test will fail complaining that you have not mocked config.getInt or whatever you use.
- Add mock setup. For example volume count config return 3 and size returns 100GB.
- assert that the volume list for this instance as returned by findPyProvider is size 3 and each one is 100GB.
Hope it helps.
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.
Had to refactor the code lil bit. Forgot to apply @RunWith(MockitoJUnitRunner.class) on top to use mock otherwise we will get null. Now its working fine. I really learnt a lot while working on this change. Please let me know if you still think, some changes are required. Thanks for all your suggestions:)
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.
💯 for right attitude!
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 looks great now!
Important tips:
Make sure to run the unittests before submit. If any fail take it seriously and rerun failed tests.
If you run sbt shell then you can do testQuick
and most of the times that only re-runs failed tests. Or you can use testOnly for specific tests. There are few flaky tests so you can ignore if they pass in subsequent run. If not then take it seriously and post on slack channel for any debugging help. Sometime there are broken tests at HEAD. Not ideal situation, I know. But given that it is easier to not spend too much time debugging and just ask around (I learned painfully :( ..)
@@ -90,7 +94,7 @@ public void testFindByProvider() { | |||
instanceType.setActive(false); | |||
instanceType.save(); | |||
InstanceType.upsert(newProvider.code, "bar", 2, 10.0, defaultDetails); |
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.
💯 for right attitude!
[yugabyte#5919] Platform: change default storage option for AWS provider to 1x250GB Description: We wanted to show default volume count to 1 on the UI for all the instance types starting with "c5./c4." Testing: When we select aws provider while creating universe, volume count was showing more than one for some instances types starting with ""c5./c4.". Now with this fix it will show only one. Will have to reset instanceTypeDetailsJson to empty for older YW instances. Co-authored-by: Jitendra Kumar <[email protected]>
Heading:
[#5919] Platform: change default storage option for AWS provider to 1x250GB
Description:
The empty volume list will be stored in the db in that case we will be using default value(volume_count, volume_size configured in refernce.conf.
Testing:
When we select aws provider while creating universe, volume count was showing more than one for some instances types starting with ""c5./c4.". Now with this fix it will show only one.
Will have to reset instanceTypeDetailsJson to empty for older YW
instances.
Added UT's as well. sbt test run results:
[info] Test com.yugabyte.yw.commissioner.TaskGarbageCollectorTest.testPurge_noneStale started
[info] Test com.yugabyte.yw.commissioner.TaskGarbageCollectorTest.testIgnorePromError started
[info] Test com.yugabyte.yw.commissioner.TaskGarbageCollectorTest.testPurge_invalidData started
[info] Test run finished: 0 failed, 0 ignored, 7 total, 0.589s
[info] Passed: Total 1092, Failed 0, Errors 0, Passed 1088, Skipped 4
[success] Total time: 575 s, completed 18 Jan, 2021 12:33:44 PM
hasher@LAP-LIN-908:~/yugabyte-db/managed$