diff --git a/dev-support/checkstyle-suppressions.xml b/dev-support/checkstyle-suppressions.xml index f20f609e94..237b839bf3 100644 --- a/dev-support/checkstyle-suppressions.xml +++ b/dev-support/checkstyle-suppressions.xml @@ -93,4 +93,5 @@ + diff --git a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql index 8ecc59f4aa..7bf9c090ea 100644 --- a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql +++ b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql @@ -2029,4 +2029,5 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',UTC_TIMESTAMP(),'Ranger 3.0.0',UTC_TIMESTAMP(),'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10065',UTC_TIMESTAMP(),'Ranger 3.0.0',UTC_TIMESTAMP(),'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10066',UTC_TIMESTAMP(),'Ranger 3.0.0',UTC_TIMESTAMP(),'localhost','Y'); +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10071',UTC_TIMESTAMP(),'Ranger 3.0.0',UTC_TIMESTAMP(),'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y'); diff --git a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql index ddca10bb5d..cbed0abb66 100644 --- a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql +++ b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql @@ -2253,5 +2253,6 @@ INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,act INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10064',sys_extract_utc(systimestamp),'Ranger 3.0.0',sys_extract_utc(systimestamp),'localhost','Y'); INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10065',sys_extract_utc(systimestamp),'Ranger 3.0.0',sys_extract_utc(systimestamp),'localhost','Y'); INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10066',sys_extract_utc(systimestamp),'Ranger 3.0.0',sys_extract_utc(systimestamp),'localhost','Y'); +INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10071',sys_extract_utc(systimestamp),'Ranger 3.0.0',sys_extract_utc(systimestamp),'localhost','Y'); INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'JAVA_PATCHES',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y'); commit; diff --git a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql index 654d19aa73..0012fcf50e 100644 --- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql +++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql @@ -2186,6 +2186,7 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',current_timestamp,'Ranger 3.0.0',current_timestamp,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10065',current_timestamp,'Ranger 3.0.0',current_timestamp,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10066',current_timestamp,'Ranger 3.0.0',current_timestamp,'localhost','Y'); +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10071',current_timestamp,'Ranger 3.0.0',current_timestamp,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y'); DROP VIEW IF EXISTS vx_principal; diff --git a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql index 678fe343b9..fb0b408d32 100644 --- a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql +++ b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql @@ -2421,6 +2421,8 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active GO INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10066',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y'); GO +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10071',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y'); +GO INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y'); GO exit diff --git a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql index 68c864e74e..042f521dc3 100644 --- a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql +++ b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql @@ -4626,5 +4626,6 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10065',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10066',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y'); +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10071',CURRENT_TIMESTAMP,'Ranger 3.0.0',CURRENT_TIMESTAMP,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y'); GO diff --git a/security-admin/src/main/java/org/apache/ranger/patch/PatchForAtlasResourceLabelUpdate_J10071.java b/security-admin/src/main/java/org/apache/ranger/patch/PatchForAtlasResourceLabelUpdate_J10071.java new file mode 100644 index 0000000000..706d3758b0 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/patch/PatchForAtlasResourceLabelUpdate_J10071.java @@ -0,0 +1,204 @@ +/* + * 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.ranger.patch; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.ranger.biz.ServiceDBStore; +import org.apache.ranger.common.RangerValidatorFactory; +import org.apache.ranger.db.RangerDaoManager; +import org.apache.ranger.entity.XXServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator; +import org.apache.ranger.plugin.model.validation.RangerValidator.Action; +import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; +import org.apache.ranger.util.CLIUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@Component +public class PatchForAtlasResourceLabelUpdate_J10071 extends BaseLoader { + private static final Logger LOG = LoggerFactory.getLogger(PatchForAtlasResourceLabelUpdate_J10071.class); + + private static final String ATLAS_SERVICE_DEF_NAME = EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_ATLAS_NAME; + + @Autowired + RangerDaoManager daoMgr; + + @Autowired + ServiceDBStore svcStore; + + @Autowired + RangerValidatorFactory validatorFactory; + + public static void main(String[] args) { + LOG.info("main()"); + + try { + PatchForAtlasResourceLabelUpdate_J10071 loader = (PatchForAtlasResourceLabelUpdate_J10071) CLIUtil.getBean(PatchForAtlasResourceLabelUpdate_J10071.class); + + loader.init(); + + while (loader.isMoreToProcess()) { + loader.load(); + } + + LOG.info("Load complete. Exiting!!!"); + + System.exit(0); + } catch (Exception e) { + LOG.error("Error loading", e); + + System.exit(1); + } + } + + @Override + public void init() throws Exception { + // Do Nothing + } + + @Override + public void printStats() { + LOG.info("PatchForAtlasResourceLabelUpdate data"); + } + + @Override + public void execLoad() { + LOG.info("==> PatchForAtlasResourceLabelUpdate_J10071.execLoad()"); + + try { + updateAtlasResourceLabels(); + } catch (Exception e) { + LOG.error("Error while updateAtlasResourceLabels()", e); + + System.exit(1); + } + + LOG.info("<== PatchForAtlasResourceLabelUpdate_J10071.execLoad()"); + } + + private void updateAtlasResourceLabels() throws Exception { + RangerServiceDef embeddedAtlasServiceDef = EmbeddedServiceDefsUtil.instance().getEmbeddedServiceDef(ATLAS_SERVICE_DEF_NAME); + + if (embeddedAtlasServiceDef == null) { + LOG.error("Embedded Atlas service-definition not found"); + + throw new RuntimeException("Embedded Atlas service-definition not found"); + } + + XXServiceDef xxServiceDef = daoMgr.getXXServiceDef().findByName(ATLAS_SERVICE_DEF_NAME); + + if (xxServiceDef == null) { + LOG.info("Atlas service-def not found in DB. No patching is needed"); + + return; + } + + RangerServiceDef dbAtlasServiceDef = svcStore.getServiceDefByName(ATLAS_SERVICE_DEF_NAME); + + if (dbAtlasServiceDef == null) { + LOG.error("Atlas service-def not found in service store"); + + throw new RuntimeException("Atlas service-def not found in service store"); + } + + Map embeddedResourcesByName = buildResourceMap(embeddedAtlasServiceDef.getResources()); + boolean updated = syncResourceLabels(dbAtlasServiceDef.getResources(), embeddedResourcesByName); + + if (updated) { + RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(svcStore); + + validator.validate(dbAtlasServiceDef, Action.UPDATE); + + RangerServiceDef ret = svcStore.updateServiceDef(dbAtlasServiceDef); + + if (ret == null) { + throw new RuntimeException("Error while updating " + ATLAS_SERVICE_DEF_NAME + " service-def"); + } + + LOG.info("Updated Atlas resource labels and descriptions from embedded service-definition"); + } else { + LOG.info("Atlas resource labels and descriptions are already up-to-date. No patching is needed"); + } + } + + private Map buildResourceMap(List resources) { + Map result = new HashMap<>(); + + if (CollectionUtils.isNotEmpty(resources)) { + for (RangerServiceDef.RangerResourceDef resource : resources) { + result.put(resource.getName(), resource); + } + } + + return result; + } + + private boolean syncResourceLabels(List dbResources, Map embeddedResourcesByName) { + boolean updated = false; + + if (CollectionUtils.isNotEmpty(dbResources)) { + for (RangerServiceDef.RangerResourceDef dbResource : dbResources) { + RangerServiceDef.RangerResourceDef embeddedResource = embeddedResourcesByName.get(dbResource.getName()); + + if (embeddedResource != null && updateResourceLabelAndDescription(dbResource, embeddedResource)) { + updated = true; + } + } + } + + return updated; + } + + private boolean updateResourceLabelAndDescription(RangerServiceDef.RangerResourceDef dbResource, RangerServiceDef.RangerResourceDef embeddedResource) { + boolean updated = false; + + if (!Objects.equals(dbResource.getLabel(), embeddedResource.getLabel())) { + dbResource.setLabel(embeddedResource.getLabel()); + + updated = true; + } + + if (!Objects.equals(dbResource.getDescription(), embeddedResource.getDescription())) { + dbResource.setDescription(embeddedResource.getDescription()); + + updated = true; + } + + if (!Objects.equals(dbResource.getRbKeyLabel(), embeddedResource.getRbKeyLabel())) { + dbResource.setRbKeyLabel(embeddedResource.getRbKeyLabel()); + + updated = true; + } + + if (!Objects.equals(dbResource.getRbKeyDescription(), embeddedResource.getRbKeyDescription())) { + dbResource.setRbKeyDescription(embeddedResource.getRbKeyDescription()); + + updated = true; + } + + return updated; + } +} diff --git a/security-admin/src/test/java/org/apache/ranger/patch/TestPatchForAtlasResourceLabelUpdate_J10071.java b/security-admin/src/test/java/org/apache/ranger/patch/TestPatchForAtlasResourceLabelUpdate_J10071.java new file mode 100644 index 0000000000..09416251fd --- /dev/null +++ b/security-admin/src/test/java/org/apache/ranger/patch/TestPatchForAtlasResourceLabelUpdate_J10071.java @@ -0,0 +1,221 @@ +/* + * 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.ranger.patch; + +import org.apache.ranger.biz.ServiceDBStore; +import org.apache.ranger.common.RangerValidatorFactory; +import org.apache.ranger.db.RangerDaoManager; +import org.apache.ranger.db.XXServiceDefDao; +import org.apache.ranger.entity.XXServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator; +import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; +import org.apache.ranger.util.CLIUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.Permission; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @generated by Cursor + * @description Unit tests for PatchForAtlasResourceLabelUpdate_J10071 + */ +@ExtendWith(MockitoExtension.class) +@TestMethodOrder(MethodOrderer.MethodName.class) +class TestPatchForAtlasResourceLabelUpdate_J10071 { + private static void setIfPresent(Object target, String fieldName, Object value) { + try { + Field f = target.getClass().getDeclaredField(fieldName); + f.setAccessible(true); + f.set(target, value); + } catch (NoSuchFieldException ignored) { + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + void testExecLoad_noAtlasServiceDefInDb() throws Exception { + try (MockedStatic utilMock = Mockito.mockStatic(EmbeddedServiceDefsUtil.class)) { + EmbeddedServiceDefsUtil util = Mockito.mock(EmbeddedServiceDefsUtil.class); + utilMock.when(EmbeddedServiceDefsUtil::instance).thenReturn(util); + + RangerServiceDef embeddedSvcDef = new RangerServiceDef(); + Mockito.when(util.getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_ATLAS_NAME)).thenReturn(embeddedSvcDef); + + PatchForAtlasResourceLabelUpdate_J10071 patch = new PatchForAtlasResourceLabelUpdate_J10071(); + RangerDaoManager daoMgr = Mockito.mock(RangerDaoManager.class); + XXServiceDefDao xxServiceDefDao = Mockito.mock(XXServiceDefDao.class); + Mockito.when(daoMgr.getXXServiceDef()).thenReturn(xxServiceDefDao); + Mockito.when(xxServiceDefDao.findByName(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_ATLAS_NAME)).thenReturn(null); + setIfPresent(patch, "daoMgr", daoMgr); + + patch.execLoad(); + patch.printStats(); + } + } + + @Test + void testExecLoad_updatesResourceLabels() throws Exception { + try (MockedStatic utilMock = Mockito.mockStatic(EmbeddedServiceDefsUtil.class)) { + EmbeddedServiceDefsUtil util = Mockito.mock(EmbeddedServiceDefsUtil.class); + utilMock.when(EmbeddedServiceDefsUtil::instance).thenReturn(util); + + RangerServiceDef.RangerResourceDef embeddedResource = new RangerServiceDef.RangerResourceDef(); + embeddedResource.setName("type-category"); + embeddedResource.setLabel("Type Category"); + embeddedResource.setDescription("Type Category"); + + RangerServiceDef embeddedSvcDef = new RangerServiceDef(); + embeddedSvcDef.setResources(Collections.singletonList(embeddedResource)); + Mockito.when(util.getEmbeddedServiceDef(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_ATLAS_NAME)).thenReturn(embeddedSvcDef); + + RangerServiceDef.RangerResourceDef dbResource = new RangerServiceDef.RangerResourceDef(); + dbResource.setName("type-category"); + dbResource.setLabel("Type Catagory"); + dbResource.setDescription("Type Catagory"); + + RangerServiceDef dbSvcDef = new RangerServiceDef(); + dbSvcDef.setResources(new ArrayList<>(Collections.singletonList(dbResource))); + + ServiceDBStore svcStore = Mockito.mock(ServiceDBStore.class); + Mockito.when(svcStore.getServiceDefByName(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_ATLAS_NAME)).thenReturn(dbSvcDef); + Mockito.when(svcStore.updateServiceDef(Mockito.any())).thenAnswer(invocation -> invocation.getArgument(0)); + + RangerValidatorFactory validatorFactory = Mockito.mock(RangerValidatorFactory.class); + RangerServiceDefValidator validator = Mockito.mock(RangerServiceDefValidator.class); + Mockito.when(validatorFactory.getServiceDefValidator(Mockito.any())).thenReturn(validator); + + XXServiceDef xxServiceDef = new XXServiceDef(); + xxServiceDef.setId(15L); + RangerDaoManager daoMgr = Mockito.mock(RangerDaoManager.class); + XXServiceDefDao xxServiceDefDao = Mockito.mock(XXServiceDefDao.class); + Mockito.when(daoMgr.getXXServiceDef()).thenReturn(xxServiceDefDao); + Mockito.when(xxServiceDefDao.findByName(EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_ATLAS_NAME)).thenReturn(xxServiceDef); + + PatchForAtlasResourceLabelUpdate_J10071 patch = new PatchForAtlasResourceLabelUpdate_J10071(); + setIfPresent(patch, "daoMgr", daoMgr); + setIfPresent(patch, "svcStore", svcStore); + setIfPresent(patch, "validatorFactory", validatorFactory); + + patch.execLoad(); + + Mockito.verify(svcStore, Mockito.times(1)).updateServiceDef(Mockito.any()); + Assertions.assertEquals("Type Category", dbResource.getLabel()); + Assertions.assertEquals("Type Category", dbResource.getDescription()); + } + } + + @Test + void testUpdateResourceLabelAndDescription() throws Exception { + PatchForAtlasResourceLabelUpdate_J10071 patch = new PatchForAtlasResourceLabelUpdate_J10071(); + Method m = PatchForAtlasResourceLabelUpdate_J10071.class.getDeclaredMethod("updateResourceLabelAndDescription", + RangerServiceDef.RangerResourceDef.class, RangerServiceDef.RangerResourceDef.class); + m.setAccessible(true); + + RangerServiceDef.RangerResourceDef dbResource = new RangerServiceDef.RangerResourceDef(); + dbResource.setLabel("Type Catagory"); + dbResource.setDescription("Type Catagory"); + + RangerServiceDef.RangerResourceDef embeddedResource = new RangerServiceDef.RangerResourceDef(); + embeddedResource.setLabel("Type Category"); + embeddedResource.setDescription("Type Category"); + + boolean updated = (boolean) m.invoke(patch, dbResource, embeddedResource); + assertTrue(updated); + + boolean updatedAgain = (boolean) m.invoke(patch, dbResource, embeddedResource); + assertFalse(updatedAgain); + } + + @Test + void testSyncResourceLabels() throws Exception { + PatchForAtlasResourceLabelUpdate_J10071 patch = new PatchForAtlasResourceLabelUpdate_J10071(); + Method sync = PatchForAtlasResourceLabelUpdate_J10071.class.getDeclaredMethod("syncResourceLabels", List.class, Map.class); + sync.setAccessible(true); + + RangerServiceDef.RangerResourceDef dbResource = new RangerServiceDef.RangerResourceDef(); + dbResource.setName("type-category"); + dbResource.setLabel("Type Catagory"); + + RangerServiceDef.RangerResourceDef embeddedResource = new RangerServiceDef.RangerResourceDef(); + embeddedResource.setName("type-category"); + embeddedResource.setLabel("Type Category"); + embeddedResource.setDescription("Type Category"); + + Map embeddedByName = new HashMap<>(); + embeddedByName.put("type-category", embeddedResource); + + List dbResources = Collections.singletonList(dbResource); + boolean updated = (boolean) sync.invoke(patch, dbResources, embeddedByName); + assertTrue(updated); + } + + @Test + void testInit_DoesNothing() throws Exception { + PatchForAtlasResourceLabelUpdate_J10071 patch = new PatchForAtlasResourceLabelUpdate_J10071(); + Assertions.assertDoesNotThrow(() -> patch.init()); + } + + @Test + void testMain_Success_ExitZero() { + SecurityManager originalSm = System.getSecurityManager(); + try (MockedStatic cliMock = Mockito.mockStatic(CLIUtil.class)) { + PatchForAtlasResourceLabelUpdate_J10071 patch = new PatchForAtlasResourceLabelUpdate_J10071(); + patch.setMoreToProcess(false); + cliMock.when(() -> CLIUtil.getBean(PatchForAtlasResourceLabelUpdate_J10071.class)).thenReturn(patch); + CLIUtil cli = Mockito.mock(CLIUtil.class); + cliMock.when(() -> CLIUtil.getBean(CLIUtil.class)).thenReturn(cli); + + System.setSecurityManager(new SecurityManager() { + @Override + public void checkExit(int status) { + throw new SecurityException(String.valueOf(status)); + } + + @Override + public void checkPermission(Permission perm) { + } + }); + + try { + PatchForAtlasResourceLabelUpdate_J10071.main(new String[] {}); + } catch (SecurityException se) { + Assertions.assertNotNull(se.getMessage()); + } + } finally { + System.setSecurityManager(originalSm); + } + } +}