diff options
author | Michael Lando <ml636r@att.com> | 2017-07-17 21:12:03 +0300 |
---|---|---|
committer | Michael Lando <ml636r@att.com> | 2017-07-17 21:12:03 +0300 |
commit | 75aacbbe1acf78fa53378f07f0a8c7769449a17e (patch) | |
tree | 68a9799eb8f4704dd9a3d513401df9bb11af7739 /asdctool | |
parent | dec02e7cc74e1c401be51bd9d266575e1e008f5f (diff) |
[SDC] rebase 1710 code
Change-Id: I532ed68979fee7840ea8a5395e7e965b155fb9f9
Signed-off-by: Michael Lando <ml636r@att.com>
Diffstat (limited to 'asdctool')
34 files changed, 1650 insertions, 68 deletions
diff --git a/asdctool/pom.xml b/asdctool/pom.xml index da1b9160fd..40eebbab5f 100644 --- a/asdctool/pom.xml +++ b/asdctool/pom.xml @@ -76,6 +76,12 @@ </dependency> <dependency> + <groupId>commons-cli</groupId> + <artifactId>commons-cli</artifactId> + <version>1.4</version> + </dependency> + + <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>${jetty.version}</version> @@ -417,6 +423,20 @@ <version>${junit.version}</version> <scope>test</scope> </dependency> + + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>${testng.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> <!-- testing end --> </dependencies> diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java index ee5171d8ab..0ef435e1c3 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1604/ServiceMigration.java @@ -706,7 +706,7 @@ public class ServiceMigration { Either<ImmutablePair<ComponentInstanceData, GraphEdge>, TitanOperationStatus> reqInst = titanGenericDao.getParentNode(UniqueIdBuilder.getKeyByNodeType(NodeTypeEnum.RelationshipInst), rel.getUniqueId(), GraphEdgeLabels.RELATIONSHIP_INST, NodeTypeEnum.ResourceInstance, ComponentInstanceData.class); if (reqInst.isRight()) { - log.debug("updateRelations : failed to fetch capabilty component instance for relation {}, error {}", rel.getUniqueId(), reqInst.right().value()); + log.debug("updateRelations : failed to fetch capability component instance for relation {}, error {}", rel.getUniqueId(), reqInst.right().value()); return false; } ComponentInstanceData requirementInstanceData = reqInst.left().value().getLeft(); @@ -917,6 +917,9 @@ public class ServiceMigration { case CP: originType = OriginTypeEnum.CP; break; + case CVFC: + originType = OriginTypeEnum.CVFC; + break; default: log.debug("updateComponentInstanceType failed, no supported resource type {} for origin resource with id {}", resourceType, originId); return false; diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java index c14301ae5e..b3f138241e 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707ArtifactUuidFix.java @@ -103,10 +103,10 @@ public class Migration1707ArtifactUuidFix { if (runMode.equals("fix") || runMode.equals("fix_only_services")) { log.info("Mode {}. Start fix", runMode); if (fix(vfLst, serviceList) == false) { - log.info("Mode {}. Fix finished withh failure", runMode); + log.info("Mode {}. Fix finished with failure", runMode); return false; } - log.info("Mode {}. Fix finished withh success", runMode); + log.info("Mode {}. Fix finished with success", runMode); } return true; diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java index 21a6ae1416..36919d7520 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707Config.java @@ -271,4 +271,9 @@ public class Migration1707Config { return new NodeTemplateMissingDataResolver<>(); } + @Bean(name = "migration1707MissingInfoFix") + public Migration1707MissingInfoFix migration1707MissingInfoFix() { + return new Migration1707MissingInfoFix(); + } + } diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java new file mode 100644 index 0000000000..ff41f12b8e --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/Migration1707MissingInfoFix.java @@ -0,0 +1,220 @@ +package org.openecomp.sdc.asdctool.impl.migration.v1707; + +import fj.data.Either; +import org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel.NodeTemplateMissingDataResolver; +import org.openecomp.sdc.be.dao.jsongraph.GraphVertex; +import org.openecomp.sdc.be.dao.jsongraph.TitanDao; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; +import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.dao.titan.TitanOperationStatus; +import org.openecomp.sdc.be.datatypes.elements.*; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; +import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; +import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; +import org.openecomp.sdc.be.model.jsontitan.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.operations.api.IServiceOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +@org.springframework.stereotype.Component("migration1707MissingInfoFix") +public class Migration1707MissingInfoFix { + + private static final Logger LOGGER = LoggerFactory.getLogger(Migration1707MissingInfoFix.class); + + @Resource(name = "service-operation") + private IServiceOperation serviceOperation; + + @Resource(name = "node-template-missing-data-resolver") + private NodeTemplateMissingDataResolver nodeTemplateMissingDataResolver; + + @Resource(name = "tosca-operation-facade") + private ToscaOperationFacade toscaOperations; + + @Resource(name = "titan-dao") + private TitanDao titanDao; + + + public boolean migrate(){ + boolean res = updateVFs(); + if(res) + res = updateServices(); + return res; + } + + private ComponentParametersView getFilter() { + ComponentParametersView filter = new ComponentParametersView(true); + filter.setIgnoreComponentInstances(false); + filter.setIgnoreArtifacts(false); + filter.setIgnoreGroups(false); + filter.setIgnoreComponentInstancesInputs(false); + return filter; + } + + // if new service has VF instances with no groups - try to fetch them from old graph + private boolean oldServiceModelRequired(Component newService) { + Predicate<ComponentInstance> vfInstanceWithNoGroups = p -> OriginTypeEnum.VF == p.getOriginType() && (null == p.getGroupInstances() || p.getGroupInstances().isEmpty()); + return null != newService.getComponentInstances() && newService.getComponentInstances().stream() + .anyMatch(vfInstanceWithNoGroups); + } + + + + private List<GraphVertex> fetchVertices(Map<GraphPropertyEnum, Object> hasProps){ + Either<List<GraphVertex>, TitanOperationStatus> componentsByCriteria = titanDao.getByCriteria(VertexTypeEnum.TOPOLOGY_TEMPLATE, hasProps, JsonParseFlagEnum.ParseAll); + if (componentsByCriteria.isRight()) { + LOGGER.debug("couldn't fetch assets from sdctitan"); + return null; + } + return componentsByCriteria.left().value(); + } + + private boolean updateVFs() { + + boolean res = true; + Map<GraphPropertyEnum, Object> hasProps = new HashMap<>(); + hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.RESOURCE.name()); + hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VF.name()); + + List<GraphVertex> resources = fetchVertices(hasProps); + if(null == resources) + return false; + ComponentParametersView filter = getFilter(); + Map<String, ToscaElement> origCompMap = new HashMap<>(); + + for (GraphVertex gv : resources) { + boolean fixed = true; + Either<Component, StorageOperationStatus> toscaElement = toscaOperations.getToscaElement(gv.getUniqueId(), filter); + if (toscaElement.isRight()) { + LOGGER.debug("Failed to fetch resource {} {}", gv.getUniqueId(), toscaElement.right().value()); + return false; + } + Component resource = toscaElement.left().value(); + Map<String, Boolean> updateMap = new HashMap<>(); + nodeTemplateMissingDataResolver.updateVFComposition(resource, origCompMap, updateMap); + if(updateMap.get(JsonConstantKeysEnum.COMPOSITION.name())){ + LOGGER.info("applying instance tosca name fix on VF {}", gv.getUniqueId()); + fixed = toscaOperations.updateComponentInstanceMetadataOfTopologyTemplate(resource).isLeft(); + } + if(updateMap.get(EdgeLabelEnum.GROUPS.name())) { + List<GroupDataDefinition> groups = new ArrayList<>(resource.getGroups()); + LOGGER.info("applying groups vertex fix on VF {}", gv.getUniqueId()); + fixed = fixed && toscaOperations.updateGroupsOnComponent(resource, ComponentTypeEnum.RESOURCE, groups).isLeft(); + } + + res = res && fixed; + titanDao.commit(); + } + return res; + } + + private Map<String, MapPropertiesDataDefinition> buildInstancesInputsMap(Component component){ + Map<String, MapPropertiesDataDefinition> instanceInputsMap = new HashMap<>(); + for (Map.Entry<String, List<ComponentInstanceInput>> entry : component.getComponentInstancesInputs().entrySet()) { + MapPropertiesDataDefinition inputsMap = new MapPropertiesDataDefinition(); + inputsMap.setMapToscaDataDefinition(entry.getValue().stream().map(e -> new PropertyDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); + instanceInputsMap.put(entry.getKey(), inputsMap); + } + return instanceInputsMap; + } + + + + private Map<String, MapGroupsDataDefinition> buildGroupInstanceMap(Component component) { + Map<String, MapGroupsDataDefinition> instGroupsMap = new HashMap<>(); + for (ComponentInstance instance : component.getComponentInstances()) { + if (instance.getGroupInstances() != null) { + MapGroupsDataDefinition groupsMap = new MapGroupsDataDefinition(); + groupsMap.setMapToscaDataDefinition(instance.getGroupInstances().stream().map(e -> new GroupInstanceDataDefinition(e)).collect(Collectors.toMap(e -> e.getName(), e -> e))); + instGroupsMap.put(instance.getUniqueId(), groupsMap); + } + } + return instGroupsMap; + } + + private <T extends ToscaDataDefinition> boolean updateDataVertex(GraphVertex componentVertex, VertexTypeEnum vertexType, EdgeLabelEnum edgeLabel, Map<String, T> dataMap){ + Either<GraphVertex, TitanOperationStatus> dataVertexEither = titanDao.getChildVertex(componentVertex, edgeLabel, JsonParseFlagEnum.ParseJson); + if (dataVertexEither.isRight()) { + if(TitanOperationStatus.NOT_FOUND != dataVertexEither.right().value()) + return false; + return (nodeTemplateMissingDataResolver.topologyTemplateOperation.assosiateElementToData(componentVertex, vertexType, edgeLabel, dataMap)).isLeft(); + } + GraphVertex dataVertex = dataVertexEither.left().value(); + dataVertex.setJson(dataMap); + return (titanDao.updateVertex(dataVertex)).isLeft(); + + } + + + private boolean updateServices(){ + + boolean res = true; + Map<GraphPropertyEnum, Object> hasProps = new HashMap<>(); + hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); + + List<GraphVertex> componentsByCriteria = fetchVertices(hasProps); + if(null == componentsByCriteria) + return false; + + ComponentParametersView filter = getFilter(); + Map<String, ToscaElement> origCompMap = new HashMap<>(); + + Predicate<ComponentInstance> containsGroupInstances = p -> null != p.getGroupInstances() && !p.getGroupInstances().isEmpty(); + + for (GraphVertex gv : componentsByCriteria) { + + boolean fixed = true; + Either<org.openecomp.sdc.be.model.Service, StorageOperationStatus> toscaElement = toscaOperations.getToscaElement(gv.getUniqueId(), filter); + if (toscaElement.isRight()) { + LOGGER.debug("Failed to fetch service {} {}", gv.getUniqueId(), toscaElement.right().value()); + return false; + } + Component service = toscaElement.left().value(); + Component oldService = null; + + if(oldServiceModelRequired(service)){ + Either<Service, StorageOperationStatus> oldServiceEither = serviceOperation.getService(gv.getUniqueId(), filter, false); + if (oldServiceEither.isRight()){ + LOGGER.debug("couldn't fetch service {} from old titan", gv.getUniqueId()); + }else { + oldService = oldServiceEither.left().value(); + oldService = oldService.getComponentInstances().stream().anyMatch(containsGroupInstances) ? oldService : null; + } + } + + Map<String, Boolean> updateMap = new HashMap<>(); + nodeTemplateMissingDataResolver.updateServiceComposition(service, origCompMap, oldService, updateMap); + if(updateMap.get(JsonConstantKeysEnum.COMPOSITION.name())) { + LOGGER.info("applying instance tosca name fix on service {}", gv.getUniqueId()); + fixed = (toscaOperations.updateComponentInstanceMetadataOfTopologyTemplate(service)).isLeft(); + } + if(updateMap.get(EdgeLabelEnum.INST_GROUPS.name())) { + Map<String, MapGroupsDataDefinition> groupsMap = buildGroupInstanceMap(service); + LOGGER.info("applying groups instances vertex fix on service {}", gv.getUniqueId()); + fixed = fixed && updateDataVertex(gv, VertexTypeEnum.INST_GROUPS, EdgeLabelEnum.INST_GROUPS, groupsMap); + } + if(updateMap.get(EdgeLabelEnum.INST_INPUTS.name())) { + Map<String, MapPropertiesDataDefinition> instInputs = buildInstancesInputsMap(service); + LOGGER.info("applying instances inputs vertex fix on service {}", gv.getUniqueId()); + fixed = fixed && updateDataVertex(gv, VertexTypeEnum.INST_INPUTS, EdgeLabelEnum.INST_INPUTS, instInputs); + } + res = res && fixed; + titanDao.commit(); + } + return res; + } +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java index d69363be89..7603a5704a 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/ComponentMigration.java @@ -109,8 +109,8 @@ public abstract class ComponentMigration <T extends Component> extends JsonModel protected void setMissingTemplateInfo(List<T> components) { Map<String, ToscaElement> origCompMap = new HashMap<>(); for (T component : components) { - List<ComponentInstance> instances = component.getComponentInstances(); - if(null != instances) { + List<ComponentInstance> instances = component.getComponentInstances(); + if(null != instances) { for (ComponentInstance instance : instances) { nodeTemplateMissingDataResolver.resolveNodeTemplateInfo(instance, origCompMap, component); nodeTemplateMissingDataResolver.fixVFGroupInstances(component, instance); diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java index 01e36345e1..c83421066c 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/impl/migration/v1707/jsonmodel/NodeTemplateMissingDataResolver.java @@ -17,23 +17,18 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - package org.openecomp.sdc.asdctool.impl.migration.v1707.jsonmodel; - - +import fj.data.Either; +import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum; import fj.data.Either; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition; -import org.openecomp.sdc.be.model.ArtifactDefinition; -import org.openecomp.sdc.be.model.Component; -import org.openecomp.sdc.be.model.ComponentInstance; -import org.openecomp.sdc.be.model.ComponentInstanceInput; -import org.openecomp.sdc.be.model.GroupDefinition; -import org.openecomp.sdc.be.model.GroupInstance; +import org.openecomp.sdc.be.model.*; import org.openecomp.sdc.be.model.jsontitan.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsontitan.datamodel.ToscaElement; +import org.openecomp.sdc.be.model.jsontitan.enums.JsonConstantKeysEnum; import org.openecomp.sdc.be.model.jsontitan.operations.TopologyTemplateOperation; import org.openecomp.sdc.be.model.jsontitan.operations.ToscaElementLifecycleOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; @@ -45,6 +40,8 @@ import org.slf4j.LoggerFactory; import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashMap; +import java.util.*; +import java.util.stream.Collectors; import java.util.List; import java.util.Map; import java.util.Optional; @@ -59,32 +56,98 @@ public class NodeTemplateMissingDataResolver <T extends Component> { private ToscaElementLifecycleOperation lifecycleOperation; @Resource(name = "topology-template-operation") - private TopologyTemplateOperation topologyTemplateOperation; + public TopologyTemplateOperation topologyTemplateOperation; public void resolveNodeTemplateInfo(ComponentInstanceDataDefinition vfInst, Map<String, ToscaElement> origCompMap, T component) { lifecycleOperation.resolveToscaComponentName(vfInst, origCompMap); if(OriginTypeEnum.VF == vfInst.getOriginType()) { - Map<String, List<ComponentInstanceInput>> componentInstancesInputs = Optional.ofNullable(component.getComponentInstancesInputs()).orElse(new HashMap<>()); - collectVFInstanceInputs(componentInstancesInputs, origCompMap, vfInst); + collectVFInstanceInputs(component, origCompMap, vfInst); + } + } + + + + + public void updateServiceComposition(Component component, Map<String, ToscaElement> origCompMap, Component oldModelService, Map<String, Boolean> updateMap){ + + boolean composition = false; + boolean instInputs = false; + boolean instGroups = false; + List<ComponentInstance> instances = component.getComponentInstances(); + if(null != instances) { + for (ComponentInstance instance : instances) { + composition = composition || lifecycleOperation.resolveToscaComponentName(instance, origCompMap); + if(OriginTypeEnum.VF == instance.getOriginType()) { + instInputs = instInputs || collectVFInstanceInputs(component, origCompMap, instance); + instGroups = instGroups || resolveInstGroupsFromOldTitanGraphAndApplyFix(component, instance, oldModelService); + } + } } + updateMap.put(JsonConstantKeysEnum.COMPOSITION.name(), composition); + updateMap.put(EdgeLabelEnum.INST_INPUTS.name(), instInputs); + updateMap.put(EdgeLabelEnum.INST_GROUPS.name(), instGroups); + } + + + public void updateVFComposition(Component component, Map<String, ToscaElement> origCompMap, Map<String, Boolean> updateMap) { + + boolean composition = false; + boolean groups = fixVFGroups(component); + List<ComponentInstance> instances = component.getComponentInstances(); + if(null != instances) { + for (ComponentInstance instance : instances) { + composition = composition || lifecycleOperation.resolveToscaComponentName(instance, origCompMap); + } + } + updateMap.put(JsonConstantKeysEnum.COMPOSITION.name(), composition); + updateMap.put(EdgeLabelEnum.GROUPS.name(), groups); + } + + + + private boolean resolveInstGroupsFromOldTitanGraphAndApplyFix(Component component, ComponentInstance instance, Component oldService){ + + boolean res = false; + //info already exists, apply fix if needed + if(null != instance.getGroupInstances() && !instance.getGroupInstances().isEmpty()) { + res = fixVFGroupInstances(component, instance); + //get group instances from old model + }else if(null != oldService){ + ComponentInstance origInstance = oldService.getComponentInstances().stream() + .filter(p -> instance.getUniqueId().equals(p.getUniqueId())) + .findAny().orElse(null); + if(null != origInstance && null != origInstance.getGroupInstances()) { + fixVFGroupInstances(oldService, origInstance); + instance.setGroupInstances(origInstance.getGroupInstances()); + res = true; + } + } + return res; } - private void collectVFInstanceInputs(Map<String, List<ComponentInstanceInput>> instInputs, Map<String, ToscaElement> origCompMap, ComponentInstanceDataDefinition vfInst) { + private boolean collectVFInstanceInputs(Component component, Map<String, ToscaElement> origCompMap, ComponentInstanceDataDefinition vfInst) { + boolean res = false; String ciUid = vfInst.getUniqueId(); String origCompUid = vfInst.getComponentUid(); + if(null == component.getComponentInstancesInputs()) + component.setComponentInstancesInputs(new HashMap<>()); + Map<String, List<ComponentInstanceInput>> componentInstInputs = component.getComponentInstancesInputs(); Either<ToscaElement, StorageOperationStatus> origComp = fetchToscaElement(origCompMap, vfInst, origCompUid); if(origComp.isRight()) - return; + return false; Map<String, PropertyDataDefinition> origVFInputs = ((TopologyTemplate)origComp.left().value()).getInputs(); if (origVFInputs != null && !origVFInputs.isEmpty()) { + res = true; Map<String, ComponentInstanceInput> collectedVFInputs = origVFInputs.values().stream() .collect(Collectors.toMap(PropertyDataDefinition::getName, ComponentInstanceInput::new)); - List<ComponentInstanceInput> instInputList = instInputs.get(ciUid); + + List<ComponentInstanceInput> instInputList = componentInstInputs.get(ciUid); Map<String, ComponentInstanceInput> existingInstInputs = ToscaDataDefinition.listToMapByName(instInputList); collectedVFInputs.putAll(existingInstInputs); List<ComponentInstanceInput> mergedList = new ArrayList<>(collectedVFInputs.values()); - instInputs.put(ciUid, mergedList); + componentInstInputs.put(ciUid, mergedList); } + return res; } private Either<ToscaElement, StorageOperationStatus> fetchToscaElement(Map<String, ToscaElement> origCompMap, ComponentInstanceDataDefinition vfInst, String origCompUid) { @@ -201,22 +264,23 @@ public class NodeTemplateMissingDataResolver <T extends Component> { return artifactLabel; } - protected boolean fixVFGroups(Component component){ - boolean res = true; - + public boolean fixVFGroups(Component component){ + boolean res = false; + Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts(); List<GroupDefinition> groups = component.getGroups(); if (groups == null || groups.isEmpty()) { - LOGGER.debug("No groups in component {} id {} ", component.getName(), component.getUniqueId()); + LOGGER.debug("No groups in component {} id {} ", component.getName(), component.getUniqueId()); return res; } for (GroupDefinition group : groups) { if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE) && deploymentArtifacts != null) { if (isProblematicGroup(group, component.getName(), deploymentArtifacts)) { - List<String> groupArtifacts = new ArrayList<String>(group.getArtifacts()); - group.getArtifacts().clear(); - group.getArtifactsUuid().clear(); + res = true; + List<String> groupArtifacts = null == group.getArtifacts()? new ArrayList<>() : new ArrayList<>(group.getArtifacts()); + group.setArtifacts(new ArrayList<>()); + group.setArtifactsUuid(new ArrayList<>()); for (String artifactId : groupArtifacts) { String artifactlabel = findArtifactLabelFromArtifactId(artifactId); LOGGER.debug("fix group: group name {} artifactId for fix {} artifactlabel {} ", group.getName(), artifactId, artifactlabel); @@ -229,19 +293,16 @@ public class NodeTemplateMissingDataResolver <T extends Component> { if (correctArtifactUUID != null && !correctArtifactUUID.isEmpty()) { group.getArtifactsUuid().add(correctArtifactUUID); } - } } } } - - } - + } return res; } - protected boolean fixVFGroupInstances(Component component, ComponentInstance instance){ - boolean res = true; + public boolean fixVFGroupInstances(Component component, ComponentInstance instance){ + boolean res = false; Map<String, ArtifactDefinition> deploymentArtifacts = instance.getDeploymentArtifacts(); List<GroupInstance> groupInstances = instance.getGroupInstances(); @@ -252,10 +313,9 @@ public class NodeTemplateMissingDataResolver <T extends Component> { for (GroupInstance group : groupInstances) { if (group.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)) { if (isProblematicGroupInstance(group, instance.getName(), component.getName(), deploymentArtifacts)) { - - LOGGER.debug("Migration1707ArtifactUuidFix fix group: resource id {}, group name {} ", component.getUniqueId(), group.getName()); - List<String> groupArtifacts = Optional.ofNullable(group.getArtifacts()).orElse(new ArrayList<>()); - + res = true; + LOGGER.debug("Migration1707ArtifactUuidFix fix group: resource id {}, group name {} ", component.getUniqueId(), group.getName()); + List<String> groupArtifacts = null == group.getArtifacts()? new ArrayList<>() : new ArrayList<>(group.getArtifacts()); group.setArtifacts(new ArrayList<>()); group.setArtifactsUuid(new ArrayList<>()); group.setGroupInstanceArtifacts(new ArrayList<>()); @@ -285,12 +345,9 @@ public class NodeTemplateMissingDataResolver <T extends Component> { } } } - } } } - return res; } - } diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java index dd9fa86084..600ebf848a 100644 --- a/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/main/MigrationMenu.java @@ -33,12 +33,7 @@ import org.openecomp.sdc.asdctool.impl.migration.v1607.CsarMigration; import org.openecomp.sdc.asdctool.impl.migration.v1610.TitanFixUtils; import org.openecomp.sdc.asdctool.impl.migration.v1610.ToscaArtifactsAlignment; import org.openecomp.sdc.asdctool.impl.migration.v1702.Migration1702; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707ArtifactUuidFix; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707Config; -import org.openecomp.sdc.asdctool.impl.migration.v1707.DistributionStatusUpdate; -import org.openecomp.sdc.asdctool.impl.migration.v1707.Migration1707VnfFix; -import org.openecomp.sdc.asdctool.impl.migration.v1707.VfModulesPropertiesAdding; +import org.openecomp.sdc.asdctool.impl.migration.v1707.*; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.common.api.ConfigurationSource; import org.openecomp.sdc.common.impl.ExternalConfiguration; @@ -53,17 +48,17 @@ public class MigrationMenu { private static final String SERVICE_MIGARTION_BEAN = "serviceMigrationBean"; private static enum MigrationOperationEnum { - MIGRATION_1602_1604("migrate-1602-1604", SERVICE_MIGARTION_BEAN), - ALIGN_DERIVED_FROM_1604("align-derived-from-1604", "derivedFromAlignment"), - MIGRATE_1604_1607("migrate-1604-1607", SERVICE_MIGARTION_BEAN), - ALIGN_VFC_NAMES_1604("align-vfc-names-1604", "vfcNamingAlignmentBean"), - TEST_REMOVE_HEAT_PLACEHOLDERS("testremoveheatplaceholders", SERVICE_MIGARTION_BEAN), - TEST_ADD_GROUP_UUIDS("testaddgroupuuids", SERVICE_MIGARTION_BEAN), - ALIGN_GROUPS("align-groups", "groupsAlignment"), - CLEAN_CSAR("clean-csar", "csarMigration"), - POPULATE_COMPONENT_CACHE("populate-component-cache", "populateComponentCache"), - FIX_PROPERTIES("fix-properties", "titanFixUtils"), - ALIGN_TOSCA_ARTIFACTS("align-tosca-artifacts", "toscaArtifactsAlignment"), + MIGRATION_1602_1604("migrate-1602-1604", SERVICE_MIGARTION_BEAN), + ALIGN_DERIVED_FROM_1604("align-derived-from-1604", "derivedFromAlignment"), + MIGRATE_1604_1607("migrate-1604-1607", SERVICE_MIGARTION_BEAN), + ALIGN_VFC_NAMES_1604("align-vfc-names-1604", "vfcNamingAlignmentBean"), + TEST_REMOVE_HEAT_PLACEHOLDERS("testremoveheatplaceholders", SERVICE_MIGARTION_BEAN), + TEST_ADD_GROUP_UUIDS("testaddgroupuuids", SERVICE_MIGARTION_BEAN), + ALIGN_GROUPS("align-groups", "groupsAlignment"), + CLEAN_CSAR("clean-csar", "csarMigration"), + POPULATE_COMPONENT_CACHE("populate-component-cache", "populateComponentCache"), + FIX_PROPERTIES("fix-properties", "titanFixUtils"), + ALIGN_TOSCA_ARTIFACTS("align-tosca-artifacts", "toscaArtifactsAlignment"), FIX_ICONS("fix-icons", "titanFixUtils"), MIGRATION_1610_1702("migrate-1610-1702", "migration1702"), MIGRATION_1702_1707("migrate-1702-1707", "migration1707"), @@ -71,7 +66,8 @@ public class MigrationMenu { VFMODULES_PROPERTIES_ADDING("vfModules-properties-adding", "vfModulesPropertiesAdding"), MIGRATION_1707_RELATIONS_FIX("fix-relations-after-migration-1707", "migration1707relationsFix"), MIGRATION_1707_VNF_FIX("fix-vnf-after-migration-1707", "migration1707vnfFix"), - MIGRATION_1707_UUID_FIX("fix-UUID-1707", "migration1707UuidFix"); + MIGRATION_1707_UUID_FIX("fix-UUID-1707", "migration1707UuidFix"), + MIGRATION_1707_MISSING_INFO_FIX("fix-missing-info-1707", "migration1707MissingInfoFix"); // UPDATE_DATA_TYPES("update_data_types", "updateDataTypes"); private String value, beanName; @@ -225,7 +221,7 @@ public class MigrationMenu { ToscaArtifactsAlignment toscaArtifactsAlignment = (ToscaArtifactsAlignment) context.getBean(operationEnum.getBeanName()); boolean isSuccessful = toscaArtifactsAlignment.alignToscaArtifacts(); if (isSuccessful) { - log.info("Tosca Artifacts alignment was finished successfull"); + log.info("Tosca Artifacts alignment was finished successfully"); System.exit(0); } else { log.info("Tosca Artifacts alignment has failed"); @@ -233,20 +229,20 @@ public class MigrationMenu { } break; case MIGRATION_1610_1702: - log.info("Start ASDC migration from 1610 to 1702"); + log.info("Start SDC migration from 1610 to 1702"); Migration1702 migration = (Migration1702) context.getBean(operationEnum.getBeanName()); isSuccessful = migration.migrate(appConfigDir); if (isSuccessful) { - log.info("ASDC migration from 1610 to 1702 was finished successful"); + log.info("SDC migration from 1610 to 1702 was finished successful"); System.exit(0); } else{ - log.info("ASDC migration from 1610 to 1702 has failed"); + log.info("SDC migration from 1610 to 1702 has failed"); System.exit(2); } - + break; case MIGRATION_1702_1707://this migration is currently not needed, but will be commented out for production env - log.info("Start ASDC migration from 1702 to 1707"); +// log.info("Start SDC migration from 1702 to 1707"); Migration1707 migration1707 = (Migration1707) context.getBean(operationEnum.getBeanName()); isSuccessful = migration1707.migrate(); if (isSuccessful) { @@ -278,8 +274,8 @@ public class MigrationMenu { } String fixServices = args[3]; String runMode = args[4]; - log.info("Start fixing artifact UUID after 1707 migration with arguments run with configutation [{}] , for [{}] services", runMode, fixServices); - + log.info("Start fixing artifact UUID after 1707 migration with arguments run with configuration [{}] , for [{}] services", runMode, fixServices); + Migration1707ArtifactUuidFix migrationFix = (Migration1707ArtifactUuidFix) context.getBean(operationEnum.getBeanName()); isSuccessful = migrationFix.migrate(fixServices, runMode); if (isSuccessful) { @@ -290,6 +286,20 @@ public class MigrationMenu { } System.exit(0); break; + case MIGRATION_1707_MISSING_INFO_FIX: + + log.info("Start fixing missing group and instance info after 1707 migration"); + + Migration1707MissingInfoFix migration1707Fix = (Migration1707MissingInfoFix) context.getBean(operationEnum.getBeanName()); + isSuccessful = migration1707Fix.migrate(); + if (isSuccessful) { + log.info("Fixing groups and node templates missing info was finished successfully"); + } else{ + log.info("Fixing groups and node templates missing info has failed"); + System.exit(2); + } + System.exit(0); + break; default: usageAndExit(); } @@ -330,5 +340,6 @@ public class MigrationMenu { System.out.println("Usage: fix-relations-after-migration-1707 <configuration dir>"); System.out.println("Usage: fix-vnf-after-migration-1707 <configuration dir>"); System.out.println("Usage: fix-UUID-1707 <configuration dir> <all/distributed_only> <services/service_vf/fix/fix_only_services>"); + System.out.println("Usage: fix-missing-info-1707 <configuration dir>"); } } diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java new file mode 100644 index 0000000000..0457c2136d --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/config/MigrationSpringConfig.java @@ -0,0 +1,59 @@ +package org.openecomp.sdc.asdctool.migration.config; + +import org.openecomp.sdc.asdctool.migration.core.SdcMigrationTool; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.resolver.MigrationResolver; +import org.openecomp.sdc.asdctool.migration.resolver.SpringBeansMigrationResolver; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.openecomp.sdc.be.dao.cassandra.CassandraClient; +import org.openecomp.sdc.be.dao.cassandra.MigrationTasksDao; +import org.openecomp.sdc.be.dao.config.DAOSpringConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@Import(DAOSpringConfig.class) +@ComponentScan({"org.openecomp.sdc.asdctool.migration.tasks",//migration tasks + "org.openecomp.sdc.be.model.operations.impl", + "org.openecomp.sdc.be.model.cache", + "org.openecomp.sdc.be.dao.titan", + "org.openecomp.sdc.be.dao.cassandra", + "org.openecomp.sdc.be.model.jsontitan.operations", + "org.openecomp.sdc.be.dao.jsongraph"}) +public class MigrationSpringConfig { + + @Autowired(required=false) + private List<Migration> migrations = new ArrayList<>(); + + @Bean(name = "sdc-migration-tool") + public SdcMigrationTool sdcMigrationTool(MigrationResolver migrationResolver, SdcRepoService sdcRepoService) { + return new SdcMigrationTool(migrationResolver, sdcRepoService); + } + + @Bean(name = "spring-migrations-resolver") + public SpringBeansMigrationResolver migrationResolver(SdcRepoService sdcRepoService) { + return new SpringBeansMigrationResolver(migrations, sdcRepoService); + } + + @Bean(name = "sdc-repo-service") + public SdcRepoService sdcRepoService(MigrationTasksDao migrationTasksDao) { + return new SdcRepoService(migrationTasksDao); + } + + @Bean(name = "sdc-migration-tasks-cassandra-dao") + public MigrationTasksDao migrationTasksDao() { + return new MigrationTasksDao(); + } + + @Bean(name = "cassandra-client") + public CassandraClient cassandraClient() { + return new CassandraClient(); + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java new file mode 100644 index 0000000000..003a27a1e4 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/DBVersion.java @@ -0,0 +1,95 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import java.math.BigInteger; + +public class DBVersion implements Comparable<DBVersion>{ + + private static final String VERSION_PARTS_SEPARATOR = "\\."; + private static final int MAJOR_PART_IDX = 0; + private static final int MINOR_PART_IDX = 1; + private BigInteger major; + private BigInteger minor; + + /** + * The current db version. should be tested against real db to verify it is compatible to the db version + */ + public static final DBVersion CURRENT_VERSION = new DBVersion(1710, 0); + + private DBVersion(BigInteger major, BigInteger minor) { + this.major = major; + this.minor = minor; + } + + private DBVersion(int major, int minor) { + this.major = BigInteger.valueOf(major); + this.minor = BigInteger.valueOf(minor); + } + + public BigInteger getMajor() { + return major; + } + + public BigInteger getMinor() { + return minor; + } + + public static DBVersion from(BigInteger major, BigInteger minor) { + return new DBVersion(major, minor); + } + + public static DBVersion fromString(String version) { + String[] split = version.split(VERSION_PARTS_SEPARATOR); + if (split.length != 2) { + throw new MigrationException("version must be of pattern: <major>.<minor>"); + } + return new DBVersion(getVersionPart(split[MAJOR_PART_IDX]), + getVersionPart(split[MINOR_PART_IDX])); + + } + + private static BigInteger getVersionPart(String versionPart) { + try { + return new BigInteger(versionPart); + } catch (NumberFormatException e) { + throw new MigrationException(String.format("version part %s is non numeric", versionPart)); + } + } + + @Override + public String toString() { + return String.format("%s.%s", major, minor); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DBVersion dbVersion = (DBVersion) o; + + return major.equals(dbVersion.major) && minor.equals(dbVersion.minor); + } + + @Override + public int hashCode() { + int result = major.hashCode(); + result = 31 * result + minor.hashCode(); + return result; + } + + @Override + public int compareTo(DBVersion o) { + if (o == null) { + return 1; + } + int majorsComparision = this.major.compareTo(o.major); + if (majorsComparision != 0) { + return majorsComparision; + } + int minorsComparision = this.minor.compareTo(o.minor); + if (minorsComparision != 0) { + return minorsComparision; + } + return 0; + } +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java new file mode 100644 index 0000000000..e9e805355e --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/MigrationException.java @@ -0,0 +1,13 @@ +package org.openecomp.sdc.asdctool.migration.core; + +public class MigrationException extends RuntimeException { + + public MigrationException(String message) { + super(message); + } + + public MigrationException(String message, RuntimeException e) { + super(message, e); + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java new file mode 100644 index 0000000000..e2691dc7f8 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationTool.java @@ -0,0 +1,62 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import org.openecomp.sdc.asdctool.migration.core.execution.MigrationExecutionResult; +import org.openecomp.sdc.asdctool.migration.core.execution.MigrationExecutorImpl; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.asdctool.migration.resolver.MigrationResolver; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class SdcMigrationTool { + + private static final Logger LOGGER = LoggerFactory.getLogger(SdcMigrationTool.class); + + private MigrationResolver migrationsResolver; + + private SdcRepoService sdcRepoService; + + public SdcMigrationTool(MigrationResolver migrationsResolver, SdcRepoService sdcRepoService) { + this.migrationsResolver = migrationsResolver; + this.sdcRepoService = sdcRepoService; + } + + public SdcMigrationTool() { + } + + public boolean migrate(boolean enforceAll) { + LOGGER.info("starting migration process"); + handleEnforceMigrationFlag(enforceAll); + List<Migration> migrations = migrationsResolver.resolveMigrations(); + LOGGER.info("there are {} migrations task to execute", migrations.size()); + for (Migration migration : migrations) { + try { + MigrationExecutionResult executionResult = new MigrationExecutorImpl().execute(migration); + if (migrationHasFailed(executionResult)) { + LOGGER.error("migration {} with version {} has failed. error msg: {}", migration.getClass().getName(), migration.getVersion().toString(), executionResult.getMsg()); + return false; + } + sdcRepoService.createMigrationTask(executionResult.toMigrationTaskEntry()); + } catch (RuntimeException e) { + LOGGER.error("migration {} with version {} has failed. error msg: {}", migration.getClass().getName(), migration.getVersion().toString(), e); + return false; + } + } + return true; + } + + private boolean migrationHasFailed(MigrationExecutionResult migrationResult) { + return migrationResult.getMigrationStatus().equals(MigrationResult.MigrationStatus.FAILED); + } + + private void handleEnforceMigrationFlag(boolean enforceAll) { + if (enforceAll) { + LOGGER.info("enforcing migration for current version"); + sdcRepoService.clearTasksForCurrentMajor(); + } + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java new file mode 100644 index 0000000000..4ebec6e440 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutionResult.java @@ -0,0 +1,70 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; + +import java.util.Date; + +public class MigrationExecutionResult { + + private MigrationResult.MigrationStatus migrationStatus; + private String msg; + private double executionTime; + private DBVersion version; + private String taskName; + + public MigrationTaskEntry toMigrationTaskEntry() { + MigrationTaskEntry migrationTaskEntry = new MigrationTaskEntry(); + migrationTaskEntry.setMajorVersion(this.getVersion().getMajor().longValue()); + migrationTaskEntry.setMinorVersion(this.getVersion().getMinor().longValue()); + migrationTaskEntry.setTimestamp(new Date()); + migrationTaskEntry.setTaskName(this.getTaskName()); + migrationTaskEntry.setTaskStatus(this.getMigrationStatus().name()); + migrationTaskEntry.setMessage(this.getMsg()); + migrationTaskEntry.setExecutionTime(this.getExecutionTime()); + return migrationTaskEntry; + } + + + public MigrationResult.MigrationStatus getMigrationStatus() { + return migrationStatus; + } + + void setMigrationStatus(MigrationResult.MigrationStatus migrationStatus) { + this.migrationStatus = migrationStatus; + } + + public String getMsg() { + return msg; + } + + void setMsg(String msg) { + this.msg = msg; + } + + double getExecutionTime() { + return executionTime; + } + + void setExecutionTime(double executionTime) { + this.executionTime = executionTime; + } + + public DBVersion getVersion() { + return version; + } + + public void setVersion(DBVersion version) { + this.version = version; + } + + String getTaskName() { + return taskName; + } + + void setTaskName(String taskName) { + this.taskName = taskName; + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java new file mode 100644 index 0000000000..aba5056b48 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutor.java @@ -0,0 +1,15 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.MigrationException; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; + +public interface MigrationExecutor { + + /** + * @param migration the migration to execute + * @return a {@link MigrationExecutionResult} with the relevant data on the current migration execution; + * @throws MigrationException in case there was an unexpected exception during migration + */ + MigrationExecutionResult execute(Migration migration) throws MigrationException; + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java new file mode 100644 index 0000000000..2e4d3ba8b0 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImpl.java @@ -0,0 +1,47 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.MigrationException; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StopWatch; + + +public class MigrationExecutorImpl implements MigrationExecutor { + + private static final Logger LOGGER = LoggerFactory.getLogger(MigrationExecutorImpl.class); + + @Override + public MigrationExecutionResult execute(Migration migration) throws MigrationException { + try { + LOGGER.info("starting migration {}. description: {}. version {}", migration.getClass().getName(), migration.description(), migration.getVersion().toString()); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + MigrationResult migrationResult = migration.migrate(); + stopWatch.stop(); + double executionTime = stopWatch.getTotalTimeSeconds(); + return logAndCreateExecutionResult(migration, migrationResult, executionTime); + } catch (RuntimeException e) { + LOGGER.error("migration {} has failed!", migration.description(), e); + throw new MigrationException("migration %s failed!!!", e); + + } + } + + private MigrationExecutionResult logAndCreateExecutionResult(Migration migration, MigrationResult migrationResult, double executionTime) { + LOGGER.info("finished migration {}. with version {}. migration status: {}, migration message: {}, execution time: {}", migration.getClass().getName(), migration.getVersion().toString(), migrationResult.getMigrationStatus().name(), migrationResult.getMsg(), executionTime); + return createMigrationTask(migration, migrationResult, executionTime); + } + + private MigrationExecutionResult createMigrationTask(Migration migration, MigrationResult migrationResult, double totalTimeSeconds) { + MigrationExecutionResult migrationExecutionResult = new MigrationExecutionResult(); + migrationExecutionResult.setExecutionTime(totalTimeSeconds); + migrationExecutionResult.setMigrationStatus(migrationResult.getMigrationStatus()); + migrationExecutionResult.setMsg(migrationResult.getMsg()); + migrationExecutionResult.setTaskName(migration.getClass().getName()); + migrationExecutionResult.setVersion(migration.getVersion()); + return migrationExecutionResult; + } + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java new file mode 100644 index 0000000000..58f201acf5 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/Migration.java @@ -0,0 +1,14 @@ +package org.openecomp.sdc.asdctool.migration.core.task; + + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; + +public interface Migration { + + String description(); + + DBVersion getVersion(); + + MigrationResult migrate(); + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java new file mode 100644 index 0000000000..8c4c090d94 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/core/task/MigrationResult.java @@ -0,0 +1,31 @@ +package org.openecomp.sdc.asdctool.migration.core.task; + +public class MigrationResult { + + private String msg; + private MigrationStatus migrationStatus; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public MigrationStatus getMigrationStatus() { + return migrationStatus; + } + + public void setMigrationStatus(MigrationStatus migrationStatus) { + this.migrationStatus = migrationStatus; + } + + public enum MigrationStatus { + COMPLETED, + COMPLETED_WITH_ERRORS, + FAILED + } + + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java new file mode 100644 index 0000000000..1e8a533624 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/main/MigrationMenu.java @@ -0,0 +1,100 @@ +package org.openecomp.sdc.asdctool.migration.main; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.openecomp.sdc.asdctool.migration.config.MigrationSpringConfig; +import org.openecomp.sdc.asdctool.migration.core.SdcMigrationTool; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class MigrationMenu { + + private final static Logger LOGGER = LoggerFactory.getLogger(MigrationMenu.class); + + public static void main(String[] args) { + CommandLine commandLine = initCmdLineOptions(args); + String appConfigDir = commandLine.getOptionValue("c"); + boolean enforceAll = commandLine.hasOption("e"); + uploadConfiguration(appConfigDir); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MigrationSpringConfig.class); + doMigrate(enforceAll, context); + + } + + private static void doMigrate(boolean enforceAll, AnnotationConfigApplicationContext context) { + SdcMigrationTool migrationTool = context.getBean(SdcMigrationTool.class); + boolean migrate = migrationTool.migrate(enforceAll); + if (migrate) { + LOGGER.info("migration completed successfully"); + System.exit(0); + } else { + LOGGER.error("migration failed"); + System.exit(1); + } + } + + private static CommandLine initCmdLineOptions(String[] args) { + Options options = buildCmdLineOptions(); + CommandLineParser parser = new DefaultParser(); + try { + // parse the command line arguments + return parser.parse( options, args ); + } + catch( ParseException exp ) { + // oops, something went wrong + System.err.println( "Parsing failed. Reason: " + exp.getMessage() ); + usageAndExit(options); + } + return null; + } + + private static void usageAndExit(Options options) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp( "yy", options ); + System.exit(1); + } + + private static Options buildCmdLineOptions() { + Option configPath = buildConfigPathOption(); + + Option enforceAll = buildEnforceAllOption(); + + Options options = new Options(); + options.addOption(configPath); + options.addOption(enforceAll); + return options; + } + + private static Option buildEnforceAllOption() { + return Option.builder("e") + .longOpt("enforceAll") + .desc("enforce running all migration steps for current version") + .build(); + } + + private static Option buildConfigPathOption() { + return Option.builder("c") + .longOpt("configFolderPath") + .required() + .hasArg() + .desc("path to sdc configuration folder - required") + .build(); + } + + private static void uploadConfiguration(String appConfigDir) { + ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir); + ConfigurationManager configurationManager = new ConfigurationManager(configurationSource); + } + + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java new file mode 100644 index 0000000000..b272d45ff0 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/MigrationResolver.java @@ -0,0 +1,16 @@ +package org.openecomp.sdc.asdctool.migration.resolver; + + +import org.openecomp.sdc.asdctool.migration.core.task.Migration; + +import java.util.List; + +public interface MigrationResolver { + + /** + * + * @return a list of {@code T} + */ + List<Migration> resolveMigrations(); + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java new file mode 100644 index 0000000000..4af5d76123 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolver.java @@ -0,0 +1,45 @@ +package org.openecomp.sdc.asdctool.migration.resolver; + + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class SpringBeansMigrationResolver implements MigrationResolver { + + private List<Migration> migrations = new ArrayList<>(); + + private SdcRepoService sdcRepoService; + + public SpringBeansMigrationResolver(List<Migration> migrations, SdcRepoService sdcRepoService) { + this.migrations = migrations; + this.sdcRepoService = sdcRepoService; + } + + @Override + public List<Migration> resolveMigrations() { + migrations.sort(Comparator.comparing(Migration::getVersion)); + return resolveNonExecutedMigrations(); + } + + //package private for testing + void setMigrations(List<Migration> migrations) { + this.migrations = migrations; + } + + private List<Migration> resolveNonExecutedMigrations() { + DBVersion latestDBVersion = sdcRepoService.getLatestDBVersion(); + return migrations.stream() + .filter(mig -> isMigrationVersionGreaterThanLatestVersion(latestDBVersion, mig)) + .collect(Collectors.toList()); + } + + private boolean isMigrationVersionGreaterThanLatestVersion(DBVersion latestDBVersion, Migration mig) { + return mig.getVersion().compareTo(latestDBVersion) > 0; + } +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java new file mode 100644 index 0000000000..2888ecb474 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoService.java @@ -0,0 +1,34 @@ +package org.openecomp.sdc.asdctool.migration.service; + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.be.dao.cassandra.MigrationTasksDao; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; + +import java.math.BigInteger; + +public class SdcRepoService { + + private MigrationTasksDao migrationTasksDao; + + public SdcRepoService(MigrationTasksDao migrationTasksDao) { + this.migrationTasksDao = migrationTasksDao; + } + + public DBVersion getLatestDBVersion() { + BigInteger currentMajorVersion = DBVersion.CURRENT_VERSION.getMajor(); + BigInteger latestMinorVersion = migrationTasksDao.getLatestMinorVersion(currentMajorVersion); + return latestMinorVersion == null ? DBVersion.from(currentMajorVersion, BigInteger.valueOf(Integer.MIN_VALUE)) : DBVersion.from(currentMajorVersion, latestMinorVersion); + } + + public void clearTasksForCurrentMajor() { + BigInteger currentMajorVersion = DBVersion.CURRENT_VERSION.getMajor(); + migrationTasksDao.deleteAllTasksForVersion(currentMajorVersion); + } + + public void createMigrationTask(MigrationTaskEntry migrationTaskEntry) { + migrationTasksDao.createMigrationTask(migrationTaskEntry); + } + + + +} diff --git a/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java new file mode 100644 index 0000000000..1302dc26a8 --- /dev/null +++ b/asdctool/src/main/java/org/openecomp/sdc/asdctool/migration/tasks/mig1710/ExampleMigration.java @@ -0,0 +1,27 @@ +//package org.openecomp.sdc.asdctool.migration.tasks.mig1710;//package org.openecomp.sdc.migration.tasks.mig1710; +// +//import org.openecomp.sdc.asdctool.migration.core.DBVersion; +//import org.openecomp.sdc.asdctool.migration.core.task.Migration; +//import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +//import org.springframework.stereotype.Component; +// +//@Component +//public class ExampleMigration implements Migration { +// +// @Override +// public String description() { +// return "some description"; +// } +// +// @Override +// public DBVersion getVersion() { +// return DBVersion.fromString("1710.0"); +// } +// +// @Override +// public MigrationResult migrate() { +// MigrationResult migrationResult = new MigrationResult(); +// migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); +// return migrationResult; +// } +//}
\ No newline at end of file diff --git a/asdctool/src/main/resources/config/configuration.yaml b/asdctool/src/main/resources/config/configuration.yaml index b998e2cf1f..0421d656be 100644 --- a/asdctool/src/main/resources/config/configuration.yaml +++ b/asdctool/src/main/resources/config/configuration.yaml @@ -507,6 +507,7 @@ cassandraConfig: - { name: sdcaudit, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - { name: sdcartifact, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} - { name: sdccomponent, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} + - { name: sdcrepository, replicationStrategy: SimpleStrategy, replicationInfo: ['1']} switchoverDetector: diff --git a/asdctool/src/main/resources/config/logback.xml b/asdctool/src/main/resources/config/logback.xml index 0426a32d9e..dadc5254a5 100644 --- a/asdctool/src/main/resources/config/logback.xml +++ b/asdctool/src/main/resources/config/logback.xml @@ -4,7 +4,16 @@ <property scope="system" name="ECOMP-subcomponent-name" value="SDC-TOOL" /> <property name="default-log-pattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{uuid}|%X{serviceInstanceID}|%thread||${ECOMP-subcomponent-name}|%X{userId}|%level|%X{alarmSeverity}|%X{localAddr}|${beFqdn}|%X{remoteAddr}|%logger{35}|%X{timer}|ActivityType=<%M>, Desc=<%msg>%n" /> - + + + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <encoder> + <pattern>${default-log-pattern}</pattern> + </encoder> + </layout> + </appender> + <appender name="DEBUG_ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${HOME}/asdctool/logs/${ECOMP-component-name}/${ECOMP-subcomponent-name}/debug.log</file> @@ -65,4 +74,8 @@ <appender-ref ref="MALFORMED_DATA"/> </logger> + <logger name="org.openecomp.sdc.asdctool.migration" level="INFO" > + <appender-ref ref="STDOUT"/> + </logger> + </configuration>
\ No newline at end of file diff --git a/asdctool/src/main/resources/scripts/postMigration1707Fix.sh b/asdctool/src/main/resources/scripts/postMigration1707Fix.sh new file mode 100644 index 0000000000..56a16db70a --- /dev/null +++ b/asdctool/src/main/resources/scripts/postMigration1707Fix.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +############################## +# Data Migration 1707 +############################## + +CURRENT_DIR=`pwd` +BASEDIR=$(dirname $0) + +if [ ${BASEDIR:0:1} = "/" ] +then + FULL_PATH=$BASEDIR +else + FULL_PATH=$CURRENT_DIR/$BASEDIR +fi + +source ${FULL_PATH}/baseOperation.sh + +mainClass="org.openecomp.sdc.asdctool.main.MigrationMenu" + +command="java $JVM_LOG_FILE -Xmx6000M -cp $JARS $mainClass fix-missing-info-1707 $@" +echo $command + +$command +result=$? + + + +echo "***********************************" +echo "***** $result *********************" +echo "***********************************" + +exit $result + + diff --git a/asdctool/src/main/resources/scripts/sdc-migration.sh b/asdctool/src/main/resources/scripts/sdc-migration.sh new file mode 100644 index 0000000000..1616890217 --- /dev/null +++ b/asdctool/src/main/resources/scripts/sdc-migration.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +############################## +# Data Migration +############################## + +CURRENT_DIR=`pwd` +BASEDIR=$(dirname $0) + +if [ ${BASEDIR:0:1} = "/" ] +then + FULL_PATH=$BASEDIR +else + FULL_PATH=$CURRENT_DIR/$BASEDIR +fi + +source ${FULL_PATH}/baseOperation.sh + +mainClass="org.openecomp.sdc.asdctool.migration.main.MigrationMenu" + +command="java $JVM_LOG_FILE -Xmx6000M -cp $JARS $mainClass $@" +echo $command + +$command +result=$? + + + +echo "***********************************" +echo "***** $result *********************" +echo "***********************************" + +exit $result + + + diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java new file mode 100644 index 0000000000..b16951ef02 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/DummyMigrationFactory.java @@ -0,0 +1,72 @@ +package org.openecomp.sdc.asdctool.migration; + + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; + +public class DummyMigrationFactory { + + public static Migration SUCCESSFUL_MIGRATION = new Migration() { + @Override + public String description() { + return "success mig"; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + }; + + public static Migration FAILED_MIGRATION = new Migration() { + @Override + public String description() { + return "failed mig"; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.FAILED); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + }; + + public static Migration getMigration(String version, MigrationResult.MigrationStatus status) { + return new Migration() { + @Override + public String description() { + return "success mig"; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString(version); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(status); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + }; + } + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java new file mode 100644 index 0000000000..4e5fd3ab31 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/DBVersionTest.java @@ -0,0 +1,57 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +public class DBVersionTest { + + + @DataProvider(name = "invalidVersionStringsProvider") + private Object[][] invalidVersionStringsProvider() { + return new Object[][] { + {"1.1.1"}, + {"1.a"}, + {"a.1"}, + {"1"} + }; + } + + @Test(dataProvider = "invalidVersionStringsProvider", expectedExceptions = MigrationException.class) + public void testFromString_invalidVersionString(String invalidVersion) { + DBVersion.fromString(invalidVersion); + } + + @DataProvider(name = "validVersionStringsProvider") + private Object[][] validVersionStringsProvider() { + return new Object[][] { + {"1.1", "1.1"}, + {"10100.0001", "10100.1"}, + {"000.1", "0.1"}, + {"01.00001000", "1.1000"}, + }; + } + + @Test(dataProvider = "validVersionStringsProvider") + public void testFromString(String validString, String expectedVersionString) { + assertEquals(expectedVersionString, DBVersion.fromString(validString).toString()); + } + + @DataProvider(name = "versionComparisionProvider") + public static Object[][] versionComparisionProvider() { + return new Object[][] { + {"1.1", "001.00001", 0}, + {"10.1", "0010.00001", 0}, + {"1.1", "001.000010", -1}, + {"1.1", "0010.00001", -1}, + {"10.10", "0010.00001", 1}, + {"1.1", "001.00", 1}, + }; + } + + @Test(dataProvider = "versionComparisionProvider") + public void testVersionCompareTo2(String firstVersion, String otherVersion, int expectedComparisionResult) throws Exception { + assertEquals(DBVersion.fromString(firstVersion).compareTo(DBVersion.fromString(otherVersion)), expectedComparisionResult); + } +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java new file mode 100644 index 0000000000..b1813227e2 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/SdcMigrationToolTest.java @@ -0,0 +1,101 @@ +package org.openecomp.sdc.asdctool.migration.core; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.internal.verification.Times; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.asdctool.migration.resolver.MigrationResolver; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class SdcMigrationToolTest { + + @InjectMocks + private SdcMigrationTool testInstance = spy(SdcMigrationTool.class); + + @Mock + private MigrationResolver migrationResolverMock; + + @Mock + private SdcRepoService sdcRepoServiceMock; + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testMigrate_noMigrations() throws Exception { + when(migrationResolverMock.resolveMigrations()).thenReturn(Collections.emptyList()); + testInstance.migrate(false); + verify(sdcRepoServiceMock, new Times(0)).clearTasksForCurrentMajor(); + verify(sdcRepoServiceMock, new Times(0)).createMigrationTask(Mockito.any()); + } + + @Test + public void testMigrate_enforceFlag_removeAllMigrationTasksForCurrentVersion() throws Exception { + when(migrationResolverMock.resolveMigrations()).thenReturn(Collections.emptyList()); + testInstance.migrate(true); + verify(sdcRepoServiceMock, new Times(1)).clearTasksForCurrentMajor(); + } + + @Test + public void testMigrate_stopAfterFirstFailure() throws Exception { + when(migrationResolverMock.resolveMigrations()).thenReturn(Arrays.asList(new SuccessfulMigration(), new FailedMigration(), new SuccessfulMigration())); + testInstance.migrate(false); + verify(sdcRepoServiceMock, new Times(0)).clearTasksForCurrentMajor(); + verify(sdcRepoServiceMock, new Times(1)).createMigrationTask(Mockito.any()); + + } + + private class FailedMigration implements Migration { + + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.FAILED); + return migrationResult; + } + } + + private class SuccessfulMigration implements Migration { + + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); + return migrationResult; + } + } +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java new file mode 100644 index 0000000000..763d6c83d2 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/core/execution/MigrationExecutorImplTest.java @@ -0,0 +1,47 @@ +package org.openecomp.sdc.asdctool.migration.core.execution; + +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +public class MigrationExecutorImplTest { + + @Test + public void testExecuteMigration() throws Exception { + MigrationExecutionResult execute = new MigrationExecutorImpl().execute(new DummyMigration()); + + } + + private void assertMigrationTaskEntryByMigrationExecutionResult(MigrationExecutionResult executionResult, Migration migration, MigrationResult result) { + assertEquals(executionResult.getMsg(), result.getMsg()); + assertEquals(executionResult.getMigrationStatus().name(), result.getMigrationStatus()); + assertEquals(executionResult.getTaskName(), migration.getClass().getName()); + assertEquals(executionResult.getVersion(), migration.getVersion()); + assertNotNull(executionResult.getExecutionTime()); + } + + private class DummyMigration implements Migration { + + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString("1710.22"); + } + + @Override + public MigrationResult migrate() { + MigrationResult migrationResult = new MigrationResult(); + migrationResult.setMigrationStatus(MigrationResult.MigrationStatus.COMPLETED); + migrationResult.setMsg("myMsg"); + return migrationResult; + } + } +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java new file mode 100644 index 0000000000..6084608f0e --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/resolver/SpringBeansMigrationResolverTest.java @@ -0,0 +1,84 @@ +package org.openecomp.sdc.asdctool.migration.resolver; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.core.task.MigrationResult; +import org.openecomp.sdc.asdctool.migration.service.SdcRepoService; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class SpringBeansMigrationResolverTest { + + @InjectMocks + private SpringBeansMigrationResolver testInstance; + + @Mock + private SdcRepoService sdcRepoServiceMock; + + private List<Migration> migrations = Arrays.asList(createMigration("1710.1"), createMigration("1710.22"), createMigration("1707.12"), createMigration("1710.3")); + + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + testInstance.setMigrations(migrations); + } + + @Test + public void testResolveMigrations_getMigrationsWithVersionGreaterThanLatest() throws Exception { + when(sdcRepoServiceMock.getLatestDBVersion()).thenReturn(DBVersion.fromString("1710.2")); + List<Migration> resolvedMigrations = testInstance.resolveMigrations(); + assertEquals(resolvedMigrations.size(), 2); + assertEquals(resolvedMigrations.get(0).getVersion(), DBVersion.fromString("1710.3")); + assertEquals(resolvedMigrations.get(1).getVersion(), DBVersion.fromString("1710.22")); + } + + @Test + public void testResolveMigration_noLatestVersionForCurrentMajorVersion() throws Exception { + when(sdcRepoServiceMock.getLatestDBVersion()).thenReturn(DBVersion.fromString("1710.-1")); + List<Migration> resolvedMigrations = testInstance.resolveMigrations(); + assertEquals(resolvedMigrations.size(), 3); + assertEquals(resolvedMigrations.get(0).getVersion(), DBVersion.fromString("1710.1")); + assertEquals(resolvedMigrations.get(1).getVersion(), DBVersion.fromString("1710.3")); + assertEquals(resolvedMigrations.get(2).getVersion(), DBVersion.fromString("1710.22")); + } + + @Test + public void testResolveMigrations_emptyMigrationsList() throws Exception { + testInstance.setMigrations(Collections.emptyList()); + when(sdcRepoServiceMock.getLatestDBVersion()).thenReturn(DBVersion.fromString("1710.-1")); + List<Migration> resolvedMigrations = testInstance.resolveMigrations(); + assertTrue(resolvedMigrations.isEmpty()); + } + + private Migration createMigration(String version) { + return new Migration() { + @Override + public String description() { + return null; + } + + @Override + public DBVersion getVersion() { + return DBVersion.fromString(version); + } + + @Override + public MigrationResult migrate() { + return null; + } + }; + } + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java new file mode 100644 index 0000000000..a2bf623b83 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/scanner/ClassScanner.java @@ -0,0 +1,81 @@ +package org.openecomp.sdc.asdctool.migration.scanner; + +import org.apache.commons.io.FileUtils; +import org.openecomp.sdc.asdctool.migration.core.MigrationException; + +import java.io.File; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * scan and instantiate classes of given type in the class path + */ +public class ClassScanner { + + + private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + public <T> List<T> getAllClassesOfType(String basePackage, Class<T> ofType) { + Collection<File> allClassesInPackage = getAllClassesInPackage(basePackage); + List<T> loadedClasses = new ArrayList<>(); + for (File clazzFile : allClassesInPackage) { + Optional<T> instance = loadAndInstantiateClass(getClassReference(clazzFile), ofType); + instance.ifPresent(loadedClasses::add); + } + return loadedClasses; + } + + private <T> Optional<T> loadAndInstantiateClass(String classReference, Class<T> ofType) { + try { + return instantiateClassOfType(classReference, ofType); + }catch (ClassNotFoundException e) { + //log + throw new MigrationException(String.format("could not find class %s of type %s. cause: %s", classReference, ofType.toGenericString(), e.getMessage())); + } catch (IllegalAccessException e1) { + //log + throw new MigrationException(String.format("could not instantiate class %s of type %s. class is not accessible. cause: %s", classReference, ofType.toGenericString(), e1.getMessage())); + } catch (InstantiationException e2) { + //log + throw new MigrationException(String.format("could not instantiate class %s of type %s. cause: %s", classReference, ofType.toGenericString(), e2.getMessage())); + } + } + + private <T> Optional<T> instantiateClassOfType(String classReference, Class<T> ofType) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + String className = classReference.replaceAll(".class$", "").replaceAll(".class", ""); + Class<?> aClass = classLoader.loadClass(className); + if (ofType.isAssignableFrom(aClass) && isInstantiateAbleClass(aClass)){ + return Optional.of((T) aClass.newInstance()); + } + return Optional.empty(); + } + + private boolean isInstantiateAbleClass(Class<?> clazz) { + return !Modifier.isAbstract(clazz.getModifiers()) && !clazz.isEnum() && !clazz.isAnonymousClass() && !clazz.isInterface(); + } + + private Collection<File> getAllClassesInPackage(String fromPackage) { + String path = fromPackage.replace(".", "/"); + URL resource = classLoader.getResource(path); + if (noMigrationTasks(resource)) { + return Collections.emptyList(); + } + return FileUtils.listFiles(new File(resource.getFile()), new String[]{"class"}, true); + } + + private boolean noMigrationTasks(URL resource) { + return resource == null; + } + + private String getClassReference(File classFile) { + String asPackage = classFile.getPath().replace(File.separator, "."); + String classes = "classes."; + return asPackage.substring(asPackage.indexOf(classes) + classes.length()); + } + + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java new file mode 100644 index 0000000000..f8e9abe2c9 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/service/SdcRepoServiceTest.java @@ -0,0 +1,55 @@ +package org.openecomp.sdc.asdctool.migration.service; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.internal.verification.Times; +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.be.dao.cassandra.MigrationTasksDao; +import org.openecomp.sdc.be.resources.data.MigrationTaskEntry; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.math.BigInteger; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertEquals; + +public class SdcRepoServiceTest { + + @InjectMocks + private SdcRepoService testInstance; + + @Mock + private MigrationTasksDao migrationTasksDaoMock; + + @BeforeMethod + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetLatestVersion_noMinorVersionForCurrentVersion() throws Exception { + when(migrationTasksDaoMock.getLatestMinorVersion(DBVersion.CURRENT_VERSION.getMajor())).thenReturn(null); + DBVersion latestDBVersion = testInstance.getLatestDBVersion(); + assertEquals(latestDBVersion.getMajor(), DBVersion.CURRENT_VERSION.getMajor()); + assertEquals(latestDBVersion.getMinor(), BigInteger.valueOf(Integer.MIN_VALUE)); + } + + @Test + public void testGetLatestVersion() throws Exception { + when(migrationTasksDaoMock.getLatestMinorVersion(DBVersion.CURRENT_VERSION.getMajor())).thenReturn(BigInteger.TEN); + DBVersion latestDBVersion = testInstance.getLatestDBVersion(); + assertEquals(latestDBVersion.getMajor(), DBVersion.CURRENT_VERSION.getMajor()); + assertEquals(latestDBVersion.getMinor(), BigInteger.TEN); + } + + @Test + public void testCreateMigrationTask() throws Exception { + MigrationTaskEntry taskEntry = new MigrationTaskEntry(); + testInstance.createMigrationTask(taskEntry); + verify(migrationTasksDaoMock, new Times(1)).createMigrationTask(taskEntry); + } + +} diff --git a/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java new file mode 100644 index 0000000000..037d51ba12 --- /dev/null +++ b/asdctool/src/test/java/org/openecomp/sdc/asdctool/migration/task/MigrationTasksTest.java @@ -0,0 +1,56 @@ +package org.openecomp.sdc.asdctool.migration.task; + +import org.apache.commons.lang.StringUtils; +import org.openecomp.sdc.asdctool.migration.core.DBVersion; +import org.openecomp.sdc.asdctool.migration.core.task.Migration; +import org.openecomp.sdc.asdctool.migration.scanner.ClassScanner; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + + +public class MigrationTasksTest { + + public static final String MIGRATIONS_BASE_PACKAGE = "org.openecomp.sdc.asdctool.migration.tasks"; + private List<Migration> migrations; + + @BeforeMethod + public void setUp() throws Exception { + ClassScanner classScanner = new ClassScanner(); + migrations = classScanner.getAllClassesOfType(MIGRATIONS_BASE_PACKAGE, Migration.class); + } + + @Test + public void testNoTasksWithSameVersion() throws Exception { + Map<DBVersion, List<Migration>> migrationsByVersion = migrations.stream().collect(Collectors.groupingBy(Migration::getVersion)); + migrationsByVersion.forEach((version, migrations) -> { + if (migrations.size() > 1) { + System.out.println(String.format("the following migration tasks have the same version %s. versions must be unique", version.toString())); + Assert.fail(String.format("migration tasks %s has same version %s. migration tasks versions must be unique.", getMigrationsNameAsString(migrations), version.toString())); + } + }); + } + + @Test + public void testNoTaskWithVersionGreaterThanCurrentVersion() throws Exception { + Set<Migration> migrationsWithVersionsGreaterThanCurrent = migrations.stream().filter(mig -> mig.getVersion().compareTo(DBVersion.CURRENT_VERSION) > 0) + .collect(Collectors.toSet()); + + if (!migrationsWithVersionsGreaterThanCurrent.isEmpty()) { + Assert.fail(String.format("migrations tasks %s have version which is greater than DBVersion.CURRENT_VERSION %s. did you forget to update current version?", + getMigrationsNameAsString(migrationsWithVersionsGreaterThanCurrent), + DBVersion.CURRENT_VERSION.toString())); + } + } + + private String getMigrationsNameAsString(Collection<Migration> migrations) { + return StringUtils.join(migrations.stream().map(mig -> mig.getClass().getName()).collect(Collectors.toList()), ","); + } +} |