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
Add TlsEngineType
enum
#5029
Add TlsEngineType
enum
#5029
Conversation
3c99037
to
9bd86a5
Compare
9bd86a5
to
027746c
Compare
} | ||
|
||
private static void setUseOpenSslAndDumpOpenSslInfo() { | ||
final boolean useOpenSsl = getValue(FlagsProvider::useOpenSsl, "useOpenSsl"); | ||
if (!useOpenSsl) { | ||
TLS_ENGINE_TYPE = getValue(FlagsProvider::tlsEngineType, "tlsEngineType"); |
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 smooth migration, -Dcom.linecorp.armeria.useOpenSsl=false
needs to return TlsEngineType.JDK
if no TlsEngineType
is specified by a user. Otherwise, an OpenSSL engine is used unexpectedly.
How about adding getUserValue()
method that ignores DefaultFlagsProvider
's values and returns only user-defined values?
final Boolean useOpenSsl = getUserValue(FlagsProvider::useOpenSsl, "useOpenSsl");
final TlsEngineType tlsEngineType = getUserValue(FlagsProvider::tlsEngineType, "tlsEngineType");
if (useOpenSsl == null) {
// Respect tlsEngineType
} else if (tlsEngineType == null) {
// Respect useOpenSsl
} else {
// Check if the values of useOpenSsl and tlsEngineType are compatible.
}
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.
@ikhoon Thank you for the detailed comment. I've added getUserValue()
which ignores DefaultFlagsProvider
.
In the case of incompatible useOpenSsl
and tlsEngineType
, I left a warning log and used the value from tlsEngineType
. I chose tlsEngineType
instead of useOpenSsl
because in that case, user is aware of and using -Dcom.linecorp.armeria.tlsEngineType
, so I think it's might be fine to use the value of tlsEngineType
.
else {
if (useOpenSsl != (tlsEngineType == TlsEngineType.OPENSSL)) {
logger.warn("useOpenSsl({}) and tlsEngineType({}) are incompatible, tlsEngineType will be used",
useOpenSsl, tlsEngineType);
}
TLS_ENGINE_TYPE = tlsEngineType;
}
027746c
to
6d2790e
Compare
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.
Looks pretty great! 👍
@@ -1506,6 +1535,29 @@ private static <T> T getValue(Function<FlagsProvider, @Nullable T> method, | |||
throw new Error(); | |||
} | |||
|
|||
@Nullable | |||
private static <T> T getUserValue(Function<FlagsProvider, @Nullable T> method, String flagName) { |
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 method looks pretty much the same as the above getValue
method.
How about removing this method and adding ignoreDefaultFlags
to the above method instead?
private static <T> T getValue(Function<FlagsProvider, @Nullable T> method,
String flagName, boolean ignoreDefaultFlags, Predicate<T> validator) {
for (FlagsProvider provider : FLAGS_PROVIDERS) {
if (provider instanceof DefaultFlagsProvider) {
continue;
}
...
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 think it's also possible to delegate the getUserValue
call to getValue
(so getValue
calls getUserValue
and falls back to DefaultFlagsProvider
)
The reasoning is although it would take up slightly more cpu cycles, I think the method itself is useful.
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 wonder how you think of getUserValue
method. Is it a temporary or not temporary?
I split the method because I thought getUserValue
method seems to be a temporary method(simply for migration and deleted afterwards). If it's not temporary, I think it's better to add ignoreDefaultFlags
.
ref: #5029 (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.
I wonder how you think of getUserValue method. Is it a temporary or not temporary?
Although temporary, we will probably keep the logic for a while (at least until 2.0)
On second thought, would it be simpler to just delete getUserValue
and modify DefaultFlagsProvider#useOpenSsl
, DefaultFlagsProvider#tlsEngineType
to return null
by 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.
@jrhee17 I think we should preserve getUserValue
because Flags#getValue
throws new Error()
when all the values retrieved by the FlagsProvider
s is null.
private static <T> T getValue(Function<FlagsProvider, @Nullable T> method,
String flagName, Predicate<T> validator) {
for (FlagsProvider provider : FLAGS_PROVIDERS) {
try {
final T value = method.apply(provider);
if (value == null) {
continue;
}
if (!validator.test(value)) {
logger.warn("{}: {} ({}, validation failed)", flagName, value, provider.name());
continue;
}
logger.info("{}: {} ({})", flagName, value, provider.name());
return value;
} catch (Exception ex) {
logger.warn("{}: ({}, {})", flagName, provider.name(), ex.getMessage());
}
}
// Should never reach here because DefaultFlagsProvider always returns a normal value.
throw new Error();
}
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, I see. Then we can probably do
if (ignoreDefaultFlags) {
return null;
}
// Should never reach here because DefaultFlagsProvider always returns a normal value.
throw new Error();
at the end.
So it's your call now. We can gather it into one method, which makes the method a little longer, or we can have separate methods. I'm fine with both. It's your call. 😉
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! I will separate methods because combining getValue
and getUserValue
will require a lot of changes when @Nullable
has to be handled by the callers of getValue
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.
Any idea on how to delegate @nullable getUserValue call to non-@nullable getValue ?
I meant something like the following. Having said this, I think I'm fine with the current approach:
diff --git a/core/src/main/java/com/linecorp/armeria/common/Flags.java b/core/src/main/java/com/linecorp/armeria/common/Flags.java
index ff40a0de6..e30115a4c 100644
--- a/core/src/main/java/com/linecorp/armeria/common/Flags.java
+++ b/core/src/main/java/com/linecorp/armeria/common/Flags.java
@@ -105,7 +105,6 @@ public final class Flags {
.sorted(Comparator.comparingInt(FlagsProvider::priority).reversed())
.collect(Collectors.toList());
flagsProviders.add(0, SystemPropertyFlagsProvider.INSTANCE);
- flagsProviders.add(DefaultFlagsProvider.INSTANCE);
FLAGS_PROVIDERS = ImmutableList.copyOf(flagsProviders);
}
@@ -561,8 +560,9 @@ public final class Flags {
return;
}
- final Boolean useOpenSsl = getUserValue(FlagsProvider::useOpenSsl, "useOpenSsl");
- final TlsEngineType tlsEngineTypeValue = getUserValue(FlagsProvider::tlsEngineType, "tlsEngineType");
+ final Boolean useOpenSsl = getUserValue(FlagsProvider::useOpenSsl, "useOpenSsl", ignored -> true);
+ final TlsEngineType tlsEngineTypeValue = getUserValue(FlagsProvider::tlsEngineType, "tlsEngineType",
+ ignored -> true);
if (useOpenSsl == null) {
tlsEngineType = tlsEngineTypeValue != null ? tlsEngineTypeValue : TlsEngineType.OPENSSL;
@@ -1549,28 +1549,16 @@ public final class Flags {
private static <T> T getValue(Function<FlagsProvider, @Nullable T> method,
String flagName, Predicate<T> validator) {
- for (FlagsProvider provider : FLAGS_PROVIDERS) {
- try {
- final T value = method.apply(provider);
- if (value == null) {
- continue;
- }
- if (!validator.test(value)) {
- logger.warn("{}: {} ({}, validation failed)", flagName, value, provider.name());
- continue;
- }
- logger.info("{}: {} ({})", flagName, value, provider.name());
- return value;
- } catch (Exception ex) {
- logger.warn("{}: ({}, {})", flagName, provider.name(), ex.getMessage());
- }
+ final T t = getUserValue(method, flagName, validator);
+ if (t != null) {
+ return t;
}
- // Should never reach here because DefaultFlagsProvider always returns a normal value.
- throw new Error();
+ return method.apply(DefaultFlagsProvider.INSTANCE);
}
@Nullable
- private static <T> T getUserValue(Function<FlagsProvider, @Nullable T> method, String flagName) {
+ private static <T> T getUserValue(Function<FlagsProvider, @Nullable T> method, String flagName,
+ Predicate<T> validator) {
for (FlagsProvider provider : FLAGS_PROVIDERS) {
if (provider instanceof DefaultFlagsProvider) {
continue;
@@ -1581,6 +1569,10 @@ public final class Flags {
if (value == null) {
continue;
}
+ if (!validator.test(value)) {
+ logger.warn("{}: {} ({}, validation failed)", flagName, value, provider.name());
+ continue;
+ }
logger.info("{}: {} ({})", flagName, value, provider.name());
return value;
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.
Oh, thanks for the great detail. I think above approach looks much clean. Let me apply above first and see whether no tests fail.
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.
@jrhee17
I think calling getUserValue
from getValue
adds some overhead because of provider instanceof DefaultFlagsProvider
(even though we don't need except for useOpenSsl
and tlsEngineType
). But I think the overheads are small. I want to first ask you whether this overheads are negligible.
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.
Left some minor comments, but mostly happy about the changes!
@@ -1506,6 +1535,29 @@ private static <T> T getValue(Function<FlagsProvider, @Nullable T> method, | |||
throw new Error(); | |||
} | |||
|
|||
@Nullable | |||
private static <T> T getUserValue(Function<FlagsProvider, @Nullable T> method, String flagName) { |
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 think it's also possible to delegate the getUserValue
call to getValue
(so getValue
calls getUserValue
and falls back to DefaultFlagsProvider
)
The reasoning is although it would take up slightly more cpu cycles, I think the method itself is useful.
core/src/main/java/com/linecorp/armeria/common/FlagsProvider.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/SystemPropertyFlagsProvider.java
Outdated
Show resolved
Hide resolved
it/flags-provider/src/test/java/com/linecorp/armeria/common/FlagsProviderTest.java
Show resolved
Hide resolved
@@ -57,7 +58,6 @@ void reloadFlags() throws ClassNotFoundException { | |||
|
|||
@Test | |||
void overrideDefaultFlagsProvider() throws Throwable { | |||
assertFlags("useOpenSsl").isEqualTo(false); |
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.
Could this be converted to the following?
assertFlags("tlsEngineType").equals(TlsEngineType.OPENSSL);
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.
Sure! I'll add that.
Btw, after adding above test code, I don't know why this keeps on failing with below exceptions. To my expectation and debugging, it should run fine...
Added code.
assertFlags("tlsEngineType").isEqualTo(TlsEngineType.OPENSSL);
Exception message:
FlagsProviderTest > overrideDefaultFlagsProvider() FAILED
java.lang.IllegalAccessException: no such method: com.linecorp.armeria.common.Flags.tlsEngineType()TlsEngineType/invokeStatic
at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:972)
at java.base/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1117)
at java.base/java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:3664)
at java.base/java.lang.invoke.MethodHandles$Lookup.findStatic(MethodHandles.java:2598)
at com.linecorp.armeria.common.FlagsProviderTest.assertFlags(FlagsProviderTest.java:163)
at com.linecorp.armeria.common.FlagsProviderTest.overrideDefaultFlagsProvider(FlagsProviderTest.java:61)
Caused by:
java.lang.LinkageError: bad method type alias: ()TlsEngineType not visible from class com.linecorp.armeria.common.Flags
at java.base/java.lang.invoke.MemberName.checkForTypeAlias(MemberName.java:878)
at java.base/java.lang.invoke.MemberName$Factory.resolve(MemberName.java:1089)
at java.base/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1114)
... 4 more
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 guess the TlsEngineType
was loaded from the default class loader, whereas the assertion is using the FlagsClassLoader
.
Can you try the following?
user@AL02437565 armeria % git diff
diff --git a/it/flags-provider/src/test/java/com/linecorp/armeria/common/FlagsProviderTest.java b/it/flags-provider/src/test/java/com/linecorp/armeria/common/FlagsProviderTest.java
index a010976bf..619bfd3eb 100644
--- a/it/flags-provider/src/test/java/com/linecorp/armeria/common/FlagsProviderTest.java
+++ b/it/flags-provider/src/test/java/com/linecorp/armeria/common/FlagsProviderTest.java
@@ -158,11 +158,8 @@ class FlagsProviderTest {
}
private ObjectAssert<Object> assertFlags(String flagsMethod) throws Throwable {
- final Lookup lookup = MethodHandles.publicLookup();
- final MethodHandle method =
- lookup.findStatic(flags, flagsMethod, MethodType.methodType(
- Flags.class.getMethod(flagsMethod).getReturnType()));
- return assertThat(method.invoke());
+ Method method = flags.getDeclaredMethod(flagsMethod);
+ return assertThat(method.invoke(null));
}
private static class FlagsClassLoader extends ClassLoader {
user@AL02437565 armeria %
I also realized it should actually be isNotEqualTo
(following the previous implementation)
core/src/test/java/com/linecorp/armeria/internal/common/util/SslContextUtilTest.java
Outdated
Show resolved
Hide resolved
System.setProperty("com.linecorp.armeria.useOpenSsl", "false"); | ||
System.setProperty("com.linecorp.armeria.tlsEngineType", "OPENSSL"); |
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 believe these values will be set while the jvm is running. Do you mind using either assumeThat
or @SetSystemProperty
instead?
System.setProperty("com.linecorp.armeria.useOpenSsl", "false"); | |
System.setProperty("com.linecorp.armeria.tlsEngineType", "OPENSSL"); | |
System.setProperty("com.linecorp.armeria.useOpenSsl", "false"); | |
System.setProperty("com.linecorp.armeria.tlsEngineType", "OPENSSL"); |
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'll change the test to use @SetSystemProperty
.
cf) I think this test leads to the problems you mentioned. Should we consider setting ways to prevent above test running in parallel(even if we use --parallel
flag)
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5029 +/- ##
===========================================
+ Coverage 0 74.08% +74.08%
- Complexity 0 20973 +20973
===========================================
Files 0 1819 +1819
Lines 0 77296 +77296
Branches 0 9874 +9874
===========================================
+ Hits 0 57267 +57267
- Misses 0 15369 +15369
- Partials 0 4660 +4660 ☔ View full report in Codecov by Sentry. |
b04c5e4
to
1e2b206
Compare
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.
Looks almost done 👍
@@ -1506,6 +1535,29 @@ private static <T> T getValue(Function<FlagsProvider, @Nullable T> method, | |||
throw new Error(); | |||
} | |||
|
|||
@Nullable | |||
private static <T> T getUserValue(Function<FlagsProvider, @Nullable T> method, String flagName) { |
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 wonder how you think of getUserValue method. Is it a temporary or not temporary?
Although temporary, we will probably keep the logic for a while (at least until 2.0)
On second thought, would it be simpler to just delete getUserValue
and modify DefaultFlagsProvider#useOpenSsl
, DefaultFlagsProvider#tlsEngineType
to return null
by default?
39a021c
to
9a84c82
Compare
We still have |
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.
Looks great! Thanks, @seonwoo960000! 😄
I think the current approach is fine for this iteration though |
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.
Looks good 👍 Thanks @seonwoo960000 🙇 👍 🙇
* <p>If {@link #tlsEngineType()} does not return {@link TlsEngineType#OPENSSL}, this also returns | ||
* {@code false} no matter you specified the JVM option. |
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.
matching the javadoc in FlagsProvider
* <p>If {@link #tlsEngineType()} does not return {@link TlsEngineType#OPENSSL}, this also returns | |
* {@code false} no matter you specified the JVM option. | |
* <p>If {@link #tlsEngineType()} does not return {@link TlsEngineType#OPENSSL}, this also returns | |
* {@code false} no matter what the specified JVM option is. |
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'll fix that right away 🏃♂️
Oh yeah, I think I've missed that point. Thank you for helping better understanding🥺 . Thank you so much of your detailed review(learned a lot!) |
9a84c82
to
9a87460
Compare
Flags.useOpenSsl = false; | ||
dumpOpenSslInfo = false; | ||
return; | ||
} | ||
if (!OpenSsl.isAvailable()) { |
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 seems a regression of #2184
Should we check OpenSsl.isAvailable()
lazily when other constrains are met?
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.
Sorry for the late reply 😅
If the cost of OpenSsl.isAvailable()
is high, I think it's better to remain as-is.
…nSslAndDumpOpenSslInfo()`
- Refactor `getValue` to delegate some logic into `getUserValue` - Fix documentation for uniformity
42a8ab6
to
0936f9a
Compare
@ikhoon Just a ping 😄. |
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.
Looks good 👍 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.
Thanks, @seonwoo960000! 🚀🚀
@minwoox (Not urgent) Could you take another look? I've re-requested a review. |
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.
Still looks good! Thanks!
I pushed a small patch that
- Adds UnstableApi
- Removes DefaultFlagsProvider.INSTANCE from flagsProrivers.
Motivation:
Add
TlsEngineType
to let users choose the type of tls engine. (UsingFlags
)Modifications:
TlsEngineType
enumuseOpenSsl
Result:
useOpenSsl
to be configured byClientFactoryBuilder
#4962 (comment)TlsEngineType
is addeduseOpenSsl
is deprecated