Healing manager logic enhancements 89/33389/2
authortalig <talig@amdocs.com>
Wed, 28 Feb 2018 08:53:11 +0000 (10:53 +0200)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Wed, 28 Feb 2018 11:28:17 +0000 (11:28 +0000)
Check whether healers need to run before running them.
Heal private: if there's at least one structure healer - force sync (instead of running data healers).

Change-Id: I5cc5ce43d61a59d5cfd6a1db717d6e3e4be1119a
Issue-ID: SDC-1066
Signed-off-by: talig <talig@amdocs.com>
openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-api/src/main/java/org/openecomp/sdc/healing/interfaces/Healer.java
openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/java/org/openecomp/sdc/healing/impl/HealingManagerImpl.java
openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-core/src/main/resources/entityHealingConfiguration.json
openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/OwnerHealer.java
openecomp-be/lib/openecomp-healing-lib/openecomp-sdc-healing-impl/src/main/java/org/openecomp/sdc/healing/healers/ToscaServiceModelHealer.java

index 13599ea..46ed591 100644 (file)
@@ -18,7 +18,9 @@ package org.openecomp.sdc.healing.interfaces;
 
 import org.openecomp.sdc.versioning.dao.types.Version;
 
-@FunctionalInterface
 public interface Healer {
-    Object heal(String itemId, Version version) throws Exception;
+
+  boolean isHealingNeeded(String itemId, Version version);
+
+  void heal(String itemId, Version version) throws Exception;
 }
index 4a0bf13..eef8c3c 100644 (file)
@@ -7,9 +7,9 @@
  * Licensed 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.
@@ -24,33 +24,29 @@ import org.openecomp.core.utilities.CommonMethods;
 import org.openecomp.core.utilities.file.FileUtils;
 import org.openecomp.core.utilities.json.JsonUtil;
 import org.openecomp.sdc.common.errors.CoreException;
+import org.openecomp.sdc.common.errors.ErrorCategory;
 import org.openecomp.sdc.common.errors.ErrorCode;
 import org.openecomp.sdc.common.errors.Messages;
-import org.openecomp.sdc.common.session.SessionContext;
 import org.openecomp.sdc.common.session.SessionContextProviderFactory;
 import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.healing.api.HealingManager;
 import org.openecomp.sdc.healing.dao.HealingDao;
 import org.openecomp.sdc.healing.interfaces.Healer;
-import org.openecomp.sdc.healing.types.HealCode;
 import org.openecomp.sdc.healing.types.HealerType;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
 
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-/**
- * Created by Talio on 11/29/2016.
- */
 public class HealingManagerImpl implements HealingManager {
 
   private static final String HEALERS_BY_ENTITY_TYPE_FILE = "entityHealingConfiguration.json";
@@ -66,134 +62,142 @@ public class HealingManagerImpl implements HealingManager {
   }
 
   @Override
-  public Optional<Version> healItemVersion(String itemId, Version version, ItemType itemType,
-                                           boolean force) {
+  public Optional<Version> healItemVersion(final String itemId, final Version version,
+                                           final ItemType itemType, final boolean force) {
     String user = getUser();
     if (force || isPrivateHealingNeededByFlag(itemId, version.getId(), user)) {
-      version = versioningManager.get(itemId, version);
-      Version origVersion = version;
-      if (version.getStatus() == VersionStatus.Certified) {
-        Optional<Version> newVersion = createNewVersion(itemId, version);
-        if (!newVersion.isPresent()) {
-          // do NOT turn off flag here (in thought of saving version calculate performance next
-          // time) because maybe next time the next version will be available (due to deletion of
-          // the taken one)
-          return Optional.empty();
-        }
-        version = newVersion.get();
+
+      Map<String, Collection<String>> healersByType = getItemHealers(itemType);
+      List<String> failureMessages = new LinkedList<>();
+      List<Healer> structureHealersToRun =
+          getHealersToRun(healersByType.get(HealerType.structure.name()), itemId, version,
+              failureMessages);
+      List<Healer> dataHealersToRun =
+          getHealersToRun(healersByType.get(HealerType.data.name()), itemId, version,
+              failureMessages);
+
+      if (structureHealersToRun.isEmpty() && dataHealersToRun.isEmpty()) {
+        markAsHealed(itemId, version.getId(), user);
+        markAsHealed(itemId, version.getId(), PUBLIC_USER);
+        return Optional.empty();
+      }
+
+      Optional<Version> healVersion = getHealVersion(itemId, version);
+      if (!healVersion.isPresent()) {
+        // do NOT turn off flag here (in thought of saving version calculate performance next
+        // time) because maybe next time the next version will be available (due to deletion of
+        // the taken one)
+        return Optional.empty();
       }
 
-      doHeal(itemId, version, origVersion, itemType, user, force);
-      return Optional.of(version);
+      failureMessages.addAll(
+          doHeal(itemId, healVersion.get(), version, structureHealersToRun, dataHealersToRun, user,
+              force));
+
+      handleFailures(failureMessages);
+      return healVersion;
     }
     return Optional.empty();
   }
 
-  private void doHeal(String itemId, Version version, Version origVersion,
-                      ItemType itemType, String user, boolean force) {
-    Optional<String> privateFailureMessages =
-        healPrivate(itemId, version, origVersion, getItemHealers(itemType), user);
+  private Optional<Version> getHealVersion(String itemId, Version version) {
+    version.setStatus(versioningManager.get(itemId, version).getStatus());
+    return version.getStatus() == VersionStatus.Certified
+        ? createNewVersion(itemId, version.getId())
+        : Optional.of(version);
+  }
+
+  private Optional<Version> createNewVersion(String itemId, String versionId) {
+    Version newVersion = new Version();
+    newVersion.setBaseId(versionId);
+    try {
+      return Optional.of(versioningManager.create(itemId, newVersion, VersionCreationMethod.major));
+    } catch (Exception e) {
+      return Optional.empty();
+    }
+  }
 
-    Optional<String> publicFailureMessages =
+  private List<String> doHeal(String itemId, Version version, Version origVersion,
+                              List<Healer> structureHealersToRun,
+                              List<Healer> dataHealersToRun, String user,
+                              boolean force) {
+    List<String> failureMessages =
         force || origVersion.getStatus() == VersionStatus.Certified ||
             isPublicHealingNeededByFlag(itemId, origVersion.getId())
-            ? healPublic(itemId, version, origVersion, getItemHealers(itemType), user)
-            : Optional.empty();
+            ? healPublic(itemId, version, origVersion, structureHealersToRun, dataHealersToRun,
+            user)
+            : new LinkedList<>();
 
-    if (privateFailureMessages.isPresent() || publicFailureMessages.isPresent()) {
-      throw new CoreException(new ErrorCode.ErrorCodeBuilder().withMessage(
-          publicFailureMessages.orElse("") + " " + privateFailureMessages.orElse(""))
-          .build());
-    }
+    failureMessages.addAll(
+        healPrivate(itemId, version, origVersion, structureHealersToRun, dataHealersToRun, user));
+
+    return failureMessages;
   }
 
-  private Optional<String> healPrivate(String itemId, Version version, Version origVersion,
-                                       Map<String, Map<String, String>> itemHealers, String user) {
-    if (origVersion.getStatus() != VersionStatus.Certified) {
-      itemHealers.remove(HealerType.structure.name());
+  private List<String> healPrivate(String itemId, Version version, Version origVersion,
+                                   List<Healer> structureHealersToRun,
+                                   List<Healer> dataHealersToRun, String user) {
+    List<String> failureMessages;
+    if (origVersion.getStatus() == VersionStatus.Certified) {
+      failureMessages = executeHealers(itemId, version,
+          Stream.concat(structureHealersToRun.stream(), dataHealersToRun.stream())
+              .collect(Collectors.toList()));
+    } else {
+      if (structureHealersToRun.isEmpty()) {
+        failureMessages = executeHealers(itemId, version, dataHealersToRun);
+      } else {
+        versioningManager.forceSync(itemId, version);
+        failureMessages = new LinkedList<>();
+      }
     }
-
-    Optional<String> privateHealingFailureMessages = executeHealers(itemId, version, itemHealers);
     markAsHealed(itemId, origVersion.getId(), user);
-    return privateHealingFailureMessages;
+    return failureMessages;
   }
 
-  private Optional<String> healPublic(String itemId, Version version, Version origVersion,
-                                      Map<String, Map<String, String>> itemHealers, String user) {
-    Optional<String> healingFailureMessages = origVersion.getStatus() == VersionStatus.Certified
-        ? Optional.empty()
-        : healPublic(itemId, version, itemHealers, user);
+  private List<String> healPublic(String itemId, Version version, Version origVersion,
+                                  List<Healer> structureHealersToRun,
+                                  List<Healer> dataHealersToRun, String user) {
+    List<String> failureMessages = origVersion.getStatus() == VersionStatus.Certified
+        ? new LinkedList<>()
+        : healPublic(itemId, version,
+            Stream.concat(structureHealersToRun.stream(), dataHealersToRun.stream())
+                .collect(Collectors.toList()), user);
 
     markAsHealed(itemId, origVersion.getId(), PUBLIC_USER);
-    return healingFailureMessages;
+    return failureMessages;
   }
 
-  private Optional<String> healPublic(String itemId, Version version,
-                                      Map<String, Map<String, String>> itemHealers, String user) {
-    SessionContext context =
-        SessionContextProviderFactory.getInstance().createInterface().get();
-    SessionContextProviderFactory.getInstance().createInterface().create(user
-        + HEALING_USER_SUFFIX,context.getTenant());
+  private List<String> healPublic(String itemId, Version version, List<Healer> healers,
+                                  String user) {
+    String tenant = SessionContextProviderFactory.getInstance().createInterface().get().getTenant();
+    SessionContextProviderFactory.getInstance().createInterface()
+        .create(user + HEALING_USER_SUFFIX, tenant);
 
-    versioningManager.sync(itemId, version);
+    versioningManager.forceSync(itemId, version);
 
-    Optional<String> healingFailureMessages = executeHealers(itemId, version, itemHealers);
+    List<String> failureMessages = executeHealers(itemId, version, healers);
     Version publicVersion = versioningManager.get(itemId, version);
 
     if (Objects.nonNull(publicVersion.getState()) && publicVersion.getState().isDirty()) {
       versioningManager.publish(itemId, version, "Healing vsp");
     }
 
-    SessionContextProviderFactory.getInstance().createInterface().create(user, context.getTenant());
-    return healingFailureMessages;
+    SessionContextProviderFactory.getInstance().createInterface().create(user, tenant);
+    return failureMessages;
   }
 
-  private Optional<Version> createNewVersion(String itemId, Version version) {
-    Version newVersion = new Version();
-    newVersion.setBaseId(version.getId());
-    try {
-      return Optional.of(versioningManager.create(itemId, newVersion, VersionCreationMethod.major));
-    } catch (Exception e) {
-      return Optional.empty();
-    }
-  }
-
-  private Optional<String> executeHealers(String itemId, Version version,
-                                          Map<String, Map<String, String>> itemHealers) {
-    List<String> healers = itemHealers.values().stream()
-        .map(Map::values)
-        .flatMap(Collection::stream)
-        .collect(Collectors.toList());
-
-    List<String> healingFailureMessages = new ArrayList<>();
-    for (String implClassName : healers) {
-      executeHealer(itemId, version, implClassName, healingFailureMessages);
-    }
-
-    return healingFailureMessages.isEmpty()
-        ? Optional.empty()
-        : Optional.of(CommonMethods.listToSeparatedString(healingFailureMessages, '\n'));
-  }
-
-
-  private Object executeHealer(String itemId, Version version, String healerClassName,
-                               List<String> healingFailureMessages) {
-    Healer healer;
-    try {
-      healer = getHealerImplInstance(healerClassName);
-    } catch (Exception e) {
-      healingFailureMessages
-          .add(String.format(Messages.CANT_LOAD_HEALING_CLASS.getErrorMessage(),
-              healerClassName));
-      return null;
+  private List<String> executeHealers(String itemId, Version version, List<Healer> healers) {
+    List<String> failureMessages = new LinkedList<>();
+    for (Healer healer : healers) {
+      try {
+        healer.heal(itemId, version);
+      } catch (Exception e) {
+        failureMessages.add(
+            String.format("Failure in healer %s: %s", healer.getClass().getName(), e.getMessage()));
+      }
     }
 
-    try {
-      return healer.heal(itemId, version);
-    } catch (Exception e) {
-      healingFailureMessages.add(e.getMessage() + " ,healer name :" + healerClassName);
-    }
-    return null;
+    return failureMessages;
   }
 
   private boolean isPrivateHealingNeededByFlag(String itemId, String version, String user) {
@@ -214,17 +218,39 @@ public class HealingManagerImpl implements HealingManager {
     healingDao.setItemHealingFlag(false, user, itemId, versionId);
   }
 
-  private Map<String, Map<String, String>> getItemHealers(ItemType itemType) {
+  private void handleFailures(List<String> failureMessages) {
+    if (!failureMessages.isEmpty()) {
+      throw new CoreException(new ErrorCode.ErrorCodeBuilder()
+          .withCategory(ErrorCategory.APPLICATION)
+          .withMessage(CommonMethods.listToSeparatedString(failureMessages, '\n')).build());
+    }
+  }
+
+  private List<Healer> getHealersToRun(Collection<String> healersClassNames, String itemId,
+                                       Version version, List<String> failureMessages) {
+    return healersClassNames.stream()
+        .map(healerClassName -> getHealerInstance(healerClassName, failureMessages))
+        .filter(Optional::isPresent)
+        .map(Optional::get)
+        .filter(healer -> healer.isHealingNeeded(itemId, version))
+        .collect(Collectors.toList());
+  }
+
+  private Optional<Healer> getHealerInstance(String healerClassName, List<String> failureMessages) {
+    try {
+      return Optional.of((Healer) Class.forName(healerClassName).getConstructor().newInstance());
+    } catch (Exception e) {
+      failureMessages
+          .add(String.format(Messages.CANT_LOAD_HEALING_CLASS.getErrorMessage(), healerClassName));
+      return Optional.empty();
+    }
+  }
+
+  private Map<String, Collection<String>> getItemHealers(ItemType itemType) {
     Map healingConfig = FileUtils
         .readViaInputStream(HEALERS_BY_ENTITY_TYPE_FILE,
             stream -> JsonUtil.json2Object(stream, Map.class));
-    return (Map<String, Map<String, String>>) healingConfig.get(itemType.name());
-  }
-
-  private Healer getHealerImplInstance(String implClassName)
-      throws InstantiationException, IllegalAccessException, InvocationTargetException,
-      NoSuchMethodException, ClassNotFoundException {
-    return (Healer) Class.forName(implClassName).getConstructor().newInstance();
+    return (Map<String, Collection<String>>) healingConfig.get(itemType.name());
   }
 
   private String getUser() {
index 64f43a6..2fc2337 100644 (file)
@@ -1,15 +1,15 @@
 {
   "vsp": {
-    "structure": {
-      "ownerHealer": "org.openecomp.sdc.healing.healers.OwnerHealer"
-    },
-    "data": {
-      "toscaServiceModelHealer": "org.openecomp.sdc.healing.healers.ToscaServiceModelHealer"
-    }
+    "structure": [
+      "org.openecomp.sdc.healing.healers.OwnerHealer"
+    ],
+    "data": [
+      "org.openecomp.sdc.healing.healers.ToscaServiceModelHealer"
+    ]
   },
   "vlm": {
-    "structure": {
-      "ownerHealer": "org.openecomp.sdc.healing.healers.OwnerHealer"
-    }
+    "structure": [
+      "org.openecomp.sdc.healing.healers.OwnerHealer"
+    ]
   }
 }
\ No newline at end of file
index 711848c..7a9b6c2 100644 (file)
@@ -19,7 +19,6 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.stream.Stream;
 
 /**
  * Created by ayalaben on 8/28/2017
@@ -33,12 +32,16 @@ public class OwnerHealer implements Healer {
   private static final SubscribersDao subscribersDao = SubscribersDaoFactory.getInstance()
       .createInterface();
 
-  public Object heal(String itemId, Version version) {
-    Stream<ItemPermissionsEntity> itemPermissions = permissionsDao.listItemPermissions(itemId)
-        .stream();
+  @Override
+  public boolean isHealingNeeded(String itemId, Version version) {
+    return permissionsDao.listItemPermissions(itemId).stream().noneMatch(this::isOwnerPermission) ||
+        isOwnerMissingOnItem(itemId);
+  }
 
+  public void heal(String itemId, Version version) {
+    Collection<ItemPermissionsEntity> itemPermissions = permissionsDao.listItemPermissions(itemId);
 
-    if (itemPermissions.noneMatch(this::isOwnerPermission)) {
+    if (itemPermissions.stream().noneMatch(this::isOwnerPermission)) {
       String currentUserId =
           SessionContextProviderFactory.getInstance().createInterface().get().getUser().getUserId()
               .replace(HEALING_USER_SUFFIX, "");
@@ -46,24 +49,22 @@ public class OwnerHealer implements Healer {
       permissionsDao.updateItemPermissions(itemId, PermissionTypes.Owner.name(),
           Collections.singleton(currentUserId), new HashSet<>());
 
-      updateItemOwner(itemId,currentUserId);
+      updateItemOwner(itemId, currentUserId);
 
-      subscribersDao.subscribe(currentUserId,itemId);
+      subscribersDao.subscribe(currentUserId, itemId);
 
-      return currentUserId;
-    } else if (!itemHasOwnerProperty(itemId)){
-    Optional<ItemPermissionsEntity> ownerOpt = itemPermissions.filter
-        (this::isOwnerPermission).findFirst();
-      if(ownerOpt.isPresent()) {
+    } else if (isOwnerMissingOnItem(itemId)) {
+      Optional<ItemPermissionsEntity> ownerOpt =
+          itemPermissions.stream().filter(this::isOwnerPermission).findFirst();
+      if (ownerOpt.isPresent()) {
         updateItemOwner(itemId, ownerOpt.get().getUserId());
       } else {
         throw new SdcRuntimeException("Unexpected error in Owner Healer. Item id: " + itemId);
       }
-  }
-    return itemPermissions.filter(this::isOwnerPermission).findFirst().get().getUserId();
+    }
   }
 
-  private void updateItemOwner(String itemId,String userId) {
+  private void updateItemOwner(String itemId, String userId) {
     Item item = new Item();
     item.setId(itemId);
     Item retrievedItem = itemDao.get(item);
@@ -73,11 +74,11 @@ public class OwnerHealer implements Healer {
     }
   }
 
-  private boolean itemHasOwnerProperty(String itemId){
+  private boolean isOwnerMissingOnItem(String itemId) {
     Item item = new Item();
     item.setId(itemId);
     Item retrievedItem = itemDao.get(item);
-    return Objects.nonNull(retrievedItem) && Objects.nonNull(retrievedItem.getOwner());
+    return Objects.nonNull(retrievedItem) && Objects.isNull(retrievedItem.getOwner());
   }
 
   private boolean isOwnerPermission(ItemPermissionsEntity permissionsEntity) {
index e07faad..4fa5328 100644 (file)
@@ -43,25 +43,28 @@ public class ToscaServiceModelHealer implements Healer {
   }
 
   @Override
-  public Object heal(String itemId, Version version) throws Exception {
+  public boolean isHealingNeeded(String itemId, Version version) {
+    OrchestrationTemplateEntity orchestrationTemplate =
+        orchestrationTemplateDao.get(itemId, version);
+    OnboardingTypesEnum onboardingTypes =
+        OnboardingTypesEnum.getOnboardingTypesEnum(orchestrationTemplate.getFileSuffix());
+
+    return Objects.nonNull(onboardingTypes) &&
+        Objects.nonNull(orchestrationTemplate.getContentData());
+  }
+
+  @Override
+  public void heal(String itemId, Version version) throws Exception {
     OrchestrationTemplateEntity orchestrationTemplateEntity =
         orchestrationTemplateDao.get(itemId, version);
     OnboardingTypesEnum type =
         OnboardingTypesEnum.getOnboardingTypesEnum(orchestrationTemplateEntity.getFileSuffix());
 
-    if (Objects.isNull(type)
-        || Objects.isNull(orchestrationTemplateEntity.getContentData())) {
-      return null;
-    }
-
     Optional<ToscaServiceModel> healedServiceModel =
         healServiceModel(orchestrationTemplateEntity, type);
 
     healedServiceModel.ifPresent(serviceModel -> serviceModelDao
         .overrideServiceModel(itemId, version, serviceModel));
-
-    return healedServiceModel;
-
   }
 
   private Optional<ToscaServiceModel> healServiceModel(
@@ -79,7 +82,6 @@ public class ToscaServiceModelHealer implements Healer {
       default:
         return Optional.empty();
     }
-
   }
 
   private FileContentHandler getFileContentHandlerForHealing(