Skip to content

Commit cd16821

Browse files
fix(roles-sync): fix CallableCache's NPE exception for caching synchronization strategy (#1077) (#1080)
* fix(roles-sync): fix callable cache NPE exception for caching synchronization strategy * fix(roles-sync): added tests --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 6d29188) Co-authored-by: Kiran Godishala <53332225+kirangodishala@users.noreply.github.com>
1 parent 8bf74c2 commit cd16821

File tree

4 files changed

+31
-2
lines changed

4 files changed

+31
-2
lines changed

fiat-roles/src/main/java/com/netflix/spinnaker/fiat/roles/CallableCache.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ Future<Result> runAndGetResult(Key key, Callable<Result> callable) {
5757
}
5858

5959
void clear(Key key) {
60+
if (key == null) {
61+
return;
62+
}
6063
try {
6164
lock.lock();
6265
var future = cache.get(key);

fiat-roles/src/main/java/com/netflix/spinnaker/fiat/roles/UserRolesSyncStrategy.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.netflix.spinnaker.fiat.roles;
1818

19+
import java.util.ArrayList;
1920
import java.util.List;
2021
import lombok.NonNull;
2122
import lombok.RequiredArgsConstructor;
@@ -61,15 +62,16 @@ public CachedSynchronizationStrategy(
6162

6263
@Override
6364
public long syncAndReturn(List<String> roles) {
65+
final List<String> nonNullRoles = (roles != null) ? roles : new ArrayList<>();
6466
try {
6567
return this.callableCache
66-
.runAndGetResult(roles, () -> this.synchronizer.syncAndReturn(roles))
68+
.runAndGetResult(nonNullRoles, () -> this.synchronizer.syncAndReturn(nonNullRoles))
6769
.get();
6870
} catch (Exception e) {
6971
log.error(e.getMessage());
7072
throw new RolesSynchronizationException();
7173
} finally {
72-
this.callableCache.clear(roles);
74+
this.callableCache.clear(nonNullRoles);
7375
}
7476
}
7577

fiat-roles/src/test/groovy/com/netflix/spinnaker/fiat/roles/CachedSynchronizationSpec.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,18 @@ class CachedSynchronizationSpec extends Specification {
7575
then:
7676
1 * mockedCache.clear(["rolea", "roleb"])
7777
}
78+
79+
def "should not fail when the roles list is null"(){
80+
setup:
81+
def mockedSynchronizer = Mock(Synchronizer)
82+
mockedSynchronizer.syncAndReturn(_ as List<String>) >> 1L
83+
def cachedSynchronization = new CachedSynchronizationStrategy(mockedSynchronizer)
84+
85+
when:
86+
cachedSynchronization.syncAndReturn(null)
87+
88+
then:
89+
noExceptionThrown()
90+
}
91+
7892
}

fiat-roles/src/test/groovy/com/netflix/spinnaker/fiat/roles/CallableCacheSpec.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ class CallableCacheSpec extends Specification {
6666
firstExecution != secondExecution
6767
}
6868

69+
def "should not throw exception when null key is supplied to clear"() {
70+
setup:
71+
def cache = new CallableCache<String, Long>()
72+
when:
73+
cache.clear(null)
74+
75+
then:
76+
noExceptionThrown()
77+
}
78+
6979
def returnValueCallable() {
7080
return { -> 1L }
7181
}

0 commit comments

Comments
 (0)