This is an automated email from the ASF dual-hosted git repository.
suvasude pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/gobblin.git
The following commit(s) were added to refs/heads/master by this push:
new 303ec0e [GOBBLIN-1402] Allow flow's requester list/owner to be updated
303ec0e is described below
commit 303ec0e99a6987db834638726d3e88daf22ef181
Author: Jack Moseley <[email protected]>
AuthorDate: Mon Mar 8 10:42:57 2021 -0800
[GOBBLIN-1402] Allow flow's requester list/owner to be updated
Closes #3238 from jack-moseley/requester-logic-
update
---
.../apache/gobblin/service/FlowConfigV2Test.java | 86 +++++++++++++++-------
.../service/FlowConfigResourceLocalHandler.java | 7 +-
.../gobblin/service/FlowConfigsResource.java | 15 +++-
.../gobblin/service/FlowConfigsV2Resource.java | 76 +++++++++++++++++--
.../apache/gobblin/service/RequesterService.java | 9 ++-
.../service/LocalGroupOwnershipServiceTest.java | 76 +++++++++++++++++++
6 files changed, 233 insertions(+), 36 deletions(-)
diff --git
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-client/src/test/java/org/apache/gobblin/service/FlowConfigV2Test.java
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-client/src/test/java/org/apache/gobblin/service/FlowConfigV2Test.java
index f393b8f..9f645cc 100644
---
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-client/src/test/java/org/apache/gobblin/service/FlowConfigV2Test.java
+++
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-client/src/test/java/org/apache/gobblin/service/FlowConfigV2Test.java
@@ -18,7 +18,6 @@
package org.apache.gobblin.service;
import java.io.File;
-import java.nio.file.Path;
import java.util.List;
import java.util.Map;
@@ -76,6 +75,8 @@ public class FlowConfigV2Test {
private static final String TEST_FLOW_NAME_5 = "testFlow5";
private static final String TEST_FLOW_NAME_6 = "testFlow6";
private static final String TEST_FLOW_NAME_7 = "testFlow7";
+ private static final String TEST_FLOW_NAME_8 = "testFlow8";
+ private static final String TEST_FLOW_NAME_9 = "testFlow9";
private static final String TEST_SCHEDULE = "0 1/0 * ? * *";
private static final String TEST_TEMPLATE_URI =
"FS:///templates/test.template";
@@ -263,42 +264,77 @@ public class FlowConfigV2Test {
}
@Test
- public void testLocalGroupOwnershipUpdates() throws Exception {
- try {
- ServiceRequester testRequester = new ServiceRequester("testName",
"USER_PRINCIPAL", "testFrom");
- _requesterService.setRequester(testRequester);
- Map<String, String> flowProperties = Maps.newHashMap();
+ public void testGroupUpdateRejected() throws Exception {
+ ServiceRequester testRequester = new ServiceRequester("testName",
"USER_PRINCIPAL", "testFrom");
+ _requesterService.setRequester(testRequester);
+ Map<String, String> flowProperties = Maps.newHashMap();
+
+ FlowConfig flowConfig = new FlowConfig().setId(new
FlowId().setFlowGroup(TEST_GROUP_NAME).setFlowName(TEST_FLOW_NAME_7))
+ .setTemplateUris(TEST_TEMPLATE_URI)
+ .setProperties(new StringMap(flowProperties))
+ .setOwningGroup("testGroup");
+
+ _client.createFlowConfig(flowConfig);
+
+ // Update should be rejected because testName is not part of dummyGroup
+ flowConfig.setOwningGroup("dummyGroup");
+ try {
+ _client.updateFlowConfig(flowConfig);
+ Assert.fail("Expected update to be rejected");
+ } catch (RestLiResponseException e) {
+ Assert.assertEquals(e.getStatus(), HttpStatus.ORDINAL_401_Unauthorized);
+ }
+ }
- FlowConfig flowConfig = new FlowConfig().setId(new
FlowId().setFlowGroup(TEST_GROUP_NAME).setFlowName(TEST_FLOW_NAME_7))
- .setTemplateUris(TEST_TEMPLATE_URI)
- .setProperties(new StringMap(flowProperties))
- .setOwningGroup("testGroup2");
+ @Test
+ public void testRequesterUpdate() throws Exception {
+ ServiceRequester testRequester = new ServiceRequester("testName",
"USER_PRINCIPAL", "testFrom");
+ ServiceRequester testRequester2 = new ServiceRequester("testName2",
"USER_PRINCIPAL", "testFrom");
+ _requesterService.setRequester(testRequester);
+ Map<String, String> flowProperties = Maps.newHashMap();
- _client.createFlowConfig(flowConfig);
+ FlowId flowId = new
FlowId().setFlowGroup(TEST_GROUP_NAME).setFlowName(TEST_FLOW_NAME_8);
+ FlowConfig flowConfig = new FlowConfig().setId(flowId)
+ .setTemplateUris(TEST_TEMPLATE_URI)
+ .setProperties(new StringMap(flowProperties))
+ .setOwningGroup("testGroup");
- } catch (RestLiResponseException e) {
- Assert.assertEquals(e.getStatus(), HttpStatus.ORDINAL_401_Unauthorized);
- }
+ _client.createFlowConfig(flowConfig);
- String filePath = this.groupConfigFile.getAbsolutePath();
- this.groupConfigFile.delete();
- this.groupConfigFile = new File(filePath);
- String groups ="{\"testGroup2\": \"testName,testName3\"}";
- Files.write(groups.getBytes(), this.groupConfigFile);
+ // testName2 takes ownership of the flow
+ flowProperties.put(RequesterService.REQUESTER_LIST,
RequesterService.serialize(Lists.newArrayList(testRequester2)));
+ flowConfig.setProperties(new StringMap(flowProperties));
+ _requesterService.setRequester(testRequester2);
+ _client.updateFlowConfig(flowConfig);
+
+ // Check that the requester list was actually updated
+ FlowConfig updatedFlowConfig = _client.getFlowConfig(flowId);
+
Assert.assertEquals(RequesterService.deserialize(updatedFlowConfig.getProperties().get(RequesterService.REQUESTER_LIST)),
+ Lists.newArrayList(testRequester2));
+ }
+ @Test
+ public void testRequesterUpdateRejected() throws Exception {
ServiceRequester testRequester = new ServiceRequester("testName",
"USER_PRINCIPAL", "testFrom");
+ ServiceRequester testRequester2 = new ServiceRequester("testName2",
"USER_PRINCIPAL", "testFrom");
_requesterService.setRequester(testRequester);
Map<String, String> flowProperties = Maps.newHashMap();
- FlowConfig flowConfig = new FlowConfig().setId(new
FlowId().setFlowGroup(TEST_GROUP_NAME).setFlowName(TEST_FLOW_NAME_7))
+ FlowConfig flowConfig = new FlowConfig().setId(new
FlowId().setFlowGroup(TEST_GROUP_NAME).setFlowName(TEST_FLOW_NAME_9))
.setTemplateUris(TEST_TEMPLATE_URI)
- .setProperties(new StringMap(flowProperties))
- .setOwningGroup("testGroup2");
+ .setProperties(new StringMap(flowProperties));
- // this should no longer fail as the localGroupOwnership service should
have updated as the file changed
_client.createFlowConfig(flowConfig);
- testRequester.setName("testName3");
- _client.deleteFlowConfig(new
FlowId().setFlowGroup(TEST_GROUP_NAME).setFlowName(TEST_FLOW_NAME_7));
+
+ // Update should be rejected because testName is not allowed to update the
owner to testName2
+ flowProperties.put(RequesterService.REQUESTER_LIST,
RequesterService.serialize(Lists.newArrayList(testRequester2)));
+ flowConfig.setProperties(new StringMap(flowProperties));
+ try {
+ _client.updateFlowConfig(flowConfig);
+ Assert.fail("Expected update to be rejected");
+ } catch (RestLiResponseException e) {
+ Assert.assertEquals(e.getStatus(), HttpStatus.ORDINAL_401_Unauthorized);
+ }
}
@AfterClass(alwaysRun = true)
diff --git
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigResourceLocalHandler.java
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigResourceLocalHandler.java
index f4ef176..7244afb 100644
---
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigResourceLocalHandler.java
+++
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigResourceLocalHandler.java
@@ -154,9 +154,12 @@ public class FlowConfigResourceLocalHandler implements
FlowConfigsResourceHandle
"flowName and flowGroup cannot be changed in update", null);
}
- // Carry forward the requester list property since it is added at time of
creation
FlowConfig originalFlowConfig = getFlowConfig(flowId);
- flowConfig.getProperties().put(RequesterService.REQUESTER_LIST,
originalFlowConfig.getProperties().get(RequesterService.REQUESTER_LIST));
+
+ if
(!flowConfig.getProperties().containsKey(RequesterService.REQUESTER_LIST)) {
+ // Carry forward the requester list property if it is not being updated
since it was added at time of creation
+ flowConfig.getProperties().put(RequesterService.REQUESTER_LIST,
originalFlowConfig.getProperties().get(RequesterService.REQUESTER_LIST));
+ }
if (isUnscheduleRequest(flowConfig)) {
// flow config is not changed if it is just a request to un-schedule
diff --git
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsResource.java
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsResource.java
index 6fdd608..9ee00c0 100644
---
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsResource.java
+++
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsResource.java
@@ -88,6 +88,11 @@ public class FlowConfigsResource extends
ComplexKeyResourceTemplate<FlowId, Empt
*/
@Override
public CreateResponse create(FlowConfig flowConfig) {
+ if (flowConfig.hasOwningGroup()) {
+ throw new FlowConfigLoggedException(HttpStatus.S_401_UNAUTHORIZED,
"Owning group property may "
+ + "not be set through flowconfigs API, use flowconfigsV2");
+ }
+
List<ServiceRequester> requesterList =
this.requesterService.findRequesters(this);
try {
@@ -109,6 +114,14 @@ public class FlowConfigsResource extends
ComplexKeyResourceTemplate<FlowId, Empt
*/
@Override
public UpdateResponse update(ComplexResourceKey<FlowId, EmptyRecord> key,
FlowConfig flowConfig) {
+ if (flowConfig.hasOwningGroup()) {
+ throw new FlowConfigLoggedException(HttpStatus.S_401_UNAUTHORIZED,
"Owning group property may "
+ + "not be set through flowconfigs API, use flowconfigsV2");
+ }
+ if
(flowConfig.getProperties().containsKey(RequesterService.REQUESTER_LIST)) {
+ throw new FlowConfigLoggedException(HttpStatus.S_401_UNAUTHORIZED,
RequesterService.REQUESTER_LIST + " property may "
+ + "not be set through flowconfigs API, use flowconfigsV2");
+ }
checkRequester(this.requesterService, get(key),
this.requesterService.findRequesters(this));
String flowGroup = key.getKey().getFlowGroup();
String flowName = key.getKey().getFlowName();
@@ -142,7 +155,7 @@ public class FlowConfigsResource extends
ComplexKeyResourceTemplate<FlowId, Empt
*/
public static void checkRequester(
RequesterService requesterService, FlowConfig originalFlowConfig,
List<ServiceRequester> requesterList) {
- if (requesterList == null) {
+ if (requesterService.isRequesterWhitelisted(requesterList)) {
return;
}
diff --git
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsV2Resource.java
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsV2Resource.java
index 49f7faa..1ea39bc 100644
---
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsV2Resource.java
+++
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/FlowConfigsV2Resource.java
@@ -17,6 +17,7 @@
package org.apache.gobblin.service;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -26,6 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableSet;
+import com.linkedin.data.transform.DataProcessingException;
import com.linkedin.restli.common.ComplexResourceKey;
import com.linkedin.restli.common.HttpStatus;
import com.linkedin.restli.common.PatchRequest;
@@ -40,9 +42,11 @@ import com.linkedin.restli.server.annotations.QueryParam;
import com.linkedin.restli.server.annotations.RestLiCollection;
import com.linkedin.restli.server.annotations.ReturnEntity;
import com.linkedin.restli.server.resources.ComplexKeyResourceTemplate;
+import com.linkedin.restli.server.util.PatchApplier;
import javax.inject.Inject;
import javax.inject.Named;
+import lombok.extern.slf4j.Slf4j;
import org.apache.gobblin.runtime.api.FlowSpecSearchObject;
@@ -50,6 +54,7 @@ import org.apache.gobblin.runtime.api.FlowSpecSearchObject;
/**
* Resource for handling flow configuration requests
*/
+@Slf4j
@RestLiCollection(name = "flowconfigsV2", namespace =
"org.apache.gobblin.service", keyName = "id")
public class FlowConfigsV2Resource extends ComplexKeyResourceTemplate<FlowId,
FlowStatusId, FlowConfig> {
private static final Logger LOG =
LoggerFactory.getLogger(FlowConfigsV2Resource.class);
@@ -155,7 +160,7 @@ public class FlowConfigsV2Resource extends
ComplexKeyResourceTemplate<FlowId, Fl
*/
@Override
public UpdateResponse update(ComplexResourceKey<FlowId, FlowStatusId> key,
FlowConfig flowConfig) {
- checkRequester(this.requesterService, get(key),
this.requesterService.findRequesters(this));
+ checkUpdateDeleteAllowed(get(key), flowConfig);
String flowGroup = key.getKey().getFlowGroup();
String flowName = key.getKey().getFlowName();
FlowId flowId = new FlowId().setFlowGroup(flowGroup).setFlowName(flowName);
@@ -170,7 +175,14 @@ public class FlowConfigsV2Resource extends
ComplexKeyResourceTemplate<FlowId, Fl
*/
@Override
public UpdateResponse update(ComplexResourceKey<FlowId, FlowStatusId> key,
PatchRequest<FlowConfig> flowConfigPatch) {
- checkRequester(this.requesterService, get(key),
this.requesterService.findRequesters(this));
+ // Apply patch to an empty FlowConfig just to check which properties are
being set
+ FlowConfig flowConfig = new FlowConfig();
+ try {
+ PatchApplier.applyPatch(flowConfig, flowConfigPatch);
+ } catch (DataProcessingException e) {
+ throw new FlowConfigLoggedException(HttpStatus.S_400_BAD_REQUEST,
"Failed to apply patch", e);
+ }
+ checkUpdateDeleteAllowed(get(key), flowConfig);
String flowGroup = key.getKey().getFlowGroup();
String flowName = key.getKey().getFlowName();
FlowId flowId = new FlowId().setFlowGroup(flowGroup).setFlowName(flowName);
@@ -184,7 +196,7 @@ public class FlowConfigsV2Resource extends
ComplexKeyResourceTemplate<FlowId, Fl
*/
@Override
public UpdateResponse delete(ComplexResourceKey<FlowId, FlowStatusId> key) {
- checkRequester(this.requesterService, get(key),
this.requesterService.findRequesters(this));
+ checkUpdateDeleteAllowed(get(key), null);
String flowGroup = key.getKey().getFlowGroup();
String flowName = key.getKey().getFlowName();
FlowId flowId = new FlowId().setFlowGroup(flowGroup).setFlowName(flowName);
@@ -209,17 +221,67 @@ public class FlowConfigsV2Resource extends
ComplexKeyResourceTemplate<FlowId, Fl
}
/**
+ * Check that this update or delete operation is allowed, throw a {@link
FlowConfigLoggedException} if not.
+ */
+ public void checkUpdateDeleteAllowed(FlowConfig originalFlowConfig,
FlowConfig updatedFlowConfig) {
+ List<ServiceRequester> requesterList =
this.requesterService.findRequesters(this);
+ if (updatedFlowConfig != null) {
+ checkPropertyUpdatesAllowed(requesterList, updatedFlowConfig);
+ }
+ checkRequester(originalFlowConfig, requesterList);
+ }
+
+ /**
+ * Check that the properties being updated are allowed to be updated. This
includes:
+ * 1. Checking that the requester is part of the owningGroup if it is being
modified
+ * 2. Checking if the {@link RequesterService#REQUESTER_LIST} is being
modified, and only allow it if a user is changing
+ * it to themselves.
+ */
+ public void checkPropertyUpdatesAllowed(List<ServiceRequester>
requesterList, FlowConfig updatedFlowConfig) {
+ if (this.requesterService.isRequesterWhitelisted(requesterList)) {
+ return;
+ }
+
+ // Check that requester is part of owning group if owning group is being
updated
+ if (updatedFlowConfig.hasOwningGroup() &&
!this.groupOwnershipService.isMemberOfGroup(requesterList,
updatedFlowConfig.getOwningGroup())) {
+ throw new FlowConfigLoggedException(HttpStatus.S_401_UNAUTHORIZED,
"Requester not part of owning group specified. Requester " + requesterList
+ + " should join group " + updatedFlowConfig.getOwningGroup() + " and
retry.");
+ }
+
+ if (updatedFlowConfig.hasProperties() &&
updatedFlowConfig.getProperties().containsKey(RequesterService.REQUESTER_LIST))
{
+ List<ServiceRequester> updatedRequesterList;
+ try {
+ updatedRequesterList =
RequesterService.deserialize(updatedFlowConfig.getProperties().get(RequesterService.REQUESTER_LIST));
+ } catch (Exception e) {
+ String exampleRequester = "";
+ try {
+ List<ServiceRequester> exampleRequesterList = new ArrayList<>();
+ exampleRequesterList.add(new ServiceRequester("name", "type",
"from"));
+ exampleRequester = " An example requester is " +
RequesterService.serialize(exampleRequesterList);
+ } catch (IOException ioe) {
+ log.error("Failed to serialize example requester list", e);
+ }
+ throw new FlowConfigLoggedException(HttpStatus.S_400_BAD_REQUEST,
RequesterService.REQUESTER_LIST + " property was "
+ + "provided but could not be deserialized." + exampleRequester, e);
+ }
+
+ if (!updatedRequesterList.equals(requesterList)) {
+ throw new FlowConfigLoggedException(HttpStatus.S_401_UNAUTHORIZED,
RequesterService.REQUESTER_LIST + " property may "
+ + "only be updated to yourself. Requesting user: " + requesterList
+ ", updated requester: " + updatedRequesterList);
+ }
+ }
+ }
+
+ /**
* Check that all {@link ServiceRequester}s in this request are contained
within the original service requester list
* or is part of the original requester's owning group when the flow was
submitted. If they are not, throw a {@link FlowConfigLoggedException} with
{@link HttpStatus#S_401_UNAUTHORIZED}.
* If there is a failure when deserializing the original requester list,
throw a {@link FlowConfigLoggedException} with
* {@link HttpStatus#S_400_BAD_REQUEST}.
- * @param requesterService the {@link RequesterService} used to verify the
requester
* @param originalFlowConfig original flow config to find original requester
* @param requesterList list of requesters for this request
*/
- public void checkRequester(
- RequesterService requesterService, FlowConfig originalFlowConfig,
List<ServiceRequester> requesterList) {
- if (requesterList == null) {
+ public void checkRequester(FlowConfig originalFlowConfig,
List<ServiceRequester> requesterList) {
+ if (this.requesterService.isRequesterWhitelisted(requesterList)) {
return;
}
diff --git
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/RequesterService.java
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/RequesterService.java
index 0db710b..03e0e41 100644
---
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/RequesterService.java
+++
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/main/java/org/apache/gobblin/service/RequesterService.java
@@ -80,6 +80,13 @@ public abstract class RequesterService {
protected abstract List<ServiceRequester> findRequesters(BaseResource
resource);
/**
+ * Return true if the requester is whitelisted to always be accepted
+ */
+ public boolean isRequesterWhitelisted(List<ServiceRequester> requesterList) {
+ return false;
+ }
+
+ /**
* returns true if the requester is allowed to make this request.
* This default implementation accepts all requesters.
* @param originalRequesterList original requester list
@@ -87,7 +94,7 @@ public abstract class RequesterService {
* @return true if the requester is allowed to make this request, false
otherwise
*/
protected boolean isRequesterAllowed(
- List<ServiceRequester> originalRequesterList, List<ServiceRequester>
currentRequesterList){
+ List<ServiceRequester> originalRequesterList, List<ServiceRequester>
currentRequesterList) {
return true;
}
}
diff --git
a/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/test/java/org/apache/gobblin/service/LocalGroupOwnershipServiceTest.java
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/test/java/org/apache/gobblin/service/LocalGroupOwnershipServiceTest.java
new file mode 100644
index 0000000..02f2feb
--- /dev/null
+++
b/gobblin-restli/gobblin-flow-config-service/gobblin-flow-config-service-server/src/test/java/org/apache/gobblin/service/LocalGroupOwnershipServiceTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.io.Files;
+import com.typesafe.config.Config;
+
+import org.apache.gobblin.config.ConfigBuilder;
+
+
+@Test(groups = { "gobblin.service" })
+public class LocalGroupOwnershipServiceTest {
+ private File _testDirectory;
+ private GroupOwnershipService groupOwnershipService;
+ private File groupConfigFile;
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ _testDirectory = Files.createTempDir();
+
+ this.groupConfigFile = new File(_testDirectory + "/TestGroups.json");
+ String groups ="{\"testGroup\": \"testName,testName2\"}";
+ Files.write(groups.getBytes(), this.groupConfigFile);
+ Config groupServiceConfig = ConfigBuilder.create()
+ .addPrimitive(LocalGroupOwnershipService.GROUP_MEMBER_LIST,
this.groupConfigFile.getAbsolutePath())
+ .build();
+
+ groupOwnershipService = new LocalGroupOwnershipService(groupServiceConfig);
+ }
+
+ @Test
+ public void testLocalGroupOwnershipUpdates() throws Exception {
+ List<ServiceRequester> testRequester = new ArrayList<>();
+ testRequester.add(new ServiceRequester("testName", "USER_PRINCIPAL",
"testFrom"));
+
+
Assert.assertFalse(this.groupOwnershipService.isMemberOfGroup(testRequester,
"testGroup2"));
+
+ String filePath = this.groupConfigFile.getAbsolutePath();
+ this.groupConfigFile.delete();
+ this.groupConfigFile = new File(filePath);
+ String groups ="{\"testGroup2\": \"testName,testName3\"}";
+ Files.write(groups.getBytes(), this.groupConfigFile);
+
+ // this should return true now as the localGroupOwnership service should
have updated as the file changed
+
Assert.assertTrue(this.groupOwnershipService.isMemberOfGroup(testRequester,
"testGroup2"));
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void tearDown() {
+ _testDirectory.delete();
+ }
+}