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();
+  }
+}

Reply via email to