Implement restore of partially deleted VSP 64/128164/7
authorvasraz <vasyl.razinkov@est.tech>
Thu, 31 Mar 2022 18:05:00 +0000 (19:05 +0100)
committerMichael Morris <michael.morris@est.tech>
Mon, 4 Apr 2022 14:06:04 +0000 (14:06 +0000)
Change-Id: I790b6cd8494e8f35c3b9891304f15272e9769a68
Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Issue-ID: SDC-3935

common-app-api/src/main/java/org/openecomp/sdc/be/csar/storage/ArtifactStorageManager.java
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java
common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java
common-be/src/test/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManagerTest.java
common-be/src/test/java/org/openecomp/sdc/be/csar/storage/NoneStorageManagerTest.java
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/pom.xml
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/src/main/java/org/openecomp/sdcrests/item/rest/services/ItemsImpl.java
openecomp-be/api/openecomp-sdc-rest-webapp/item-rest/item-rest-services/src/test/java/org/openecomp/sdcrests/item/rest/services/ItemsImplTest.java

index 1845f85..fce566d 100644 (file)
@@ -76,4 +76,11 @@ public interface ArtifactStorageManager {
      */
     void delete(String vspId);
 
+    /**
+     * Check if VSP exists
+     *
+     * @param vspId - VSP ID
+     * @return {@code true} if exists, {@code false} otherwise
+     */
+    boolean exists(String vspId);
 }
index 78ee4be..991b3b2 100644 (file)
@@ -205,6 +205,12 @@ public class MinIoStorageArtifactStorageManager implements ArtifactStorageManage
         }
     }
 
+    @Override
+    public boolean exists(final String vspId) {
+        LOGGER.debug("exists - bucket: '{}'", vspId);
+        return bucketExists(vspId);
+    }
+
     private MinIoStorageArtifactStorageConfig readMinIoStorageArtifactStorageConfig() {
         final var commonConfigurationManager = CommonConfigurationManager.getInstance();
         final Map<String, Object> endpoint = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, ENDPOINT, null);
index 562be2d..e718b7a 100644 (file)
@@ -66,4 +66,9 @@ public class NoneStorageManager implements ArtifactStorageManager {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public boolean exists(final String vspId) {
+        throw new UnsupportedOperationException();
+    }
+
 }
index 4d12a0b..d6a52c5 100644 (file)
@@ -35,9 +35,11 @@ import io.minio.GetObjectArgs;
 import io.minio.GetObjectResponse;
 import io.minio.MakeBucketArgs;
 import io.minio.MinioClient;
+import io.minio.PutObjectArgs;
 import io.minio.RemoveBucketArgs;
 import io.minio.RemoveObjectArgs;
 import io.minio.StatObjectArgs;
+import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -141,6 +143,14 @@ class MinIoStorageArtifactStorageManagerTest {
         });
     }
 
+    @Test
+    void testPutFail() throws Exception {
+        doThrow(new RuntimeException()).when(minioClient).putObject(any(PutObjectArgs.class));
+        assertThrows(ArtifactStorageException.class, () -> {
+            testSubject.put(VSP_ID, VERSION_ID, new ByteArrayInputStream(new byte[0]));
+        });
+    }
+
     @Test
     void testIsEnabled() {
         Assertions.assertTrue(testSubject.isEnabled());
@@ -188,6 +198,20 @@ class MinIoStorageArtifactStorageManagerTest {
         });
     }
 
+    @Test
+    void testIsExistsOK() throws Exception {
+        when(minioClient.bucketExists(any(BucketExistsArgs.class))).thenReturn(true);
+        Assertions.assertTrue(testSubject.exists(VSP_ID));
+    }
+
+    @Test
+    void testIsExistsFail() throws Exception {
+        doThrow(new RuntimeException()).when(minioClient).bucketExists(any(BucketExistsArgs.class));
+        assertThrows(ArtifactStorageException.class, () -> {
+            Assertions.assertTrue(testSubject.exists(VSP_ID));
+        });
+    }
+
     private Attachment mockAttachment() throws IOException {
         final Attachment attachment = Mockito.mock(Attachment.class);
         final DataHandler dataHandler = Mockito.mock(DataHandler.class);
index 58394b9..994cbb5 100644 (file)
@@ -30,7 +30,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
 @ExtendWith(MockitoExtension.class)
 class NoneStorageManagerTest {
 
-    public static final MinIoArtifactInfo UPLOADED_ARTIFACT_INFO = new MinIoArtifactInfo("bucket", "object");
+    public static final String VSP_ID = "vsp-id";
+    public static final String VERSION_ID = "version-id";
+    public static final MinIoArtifactInfo UPLOADED_ARTIFACT_INFO = new MinIoArtifactInfo(VSP_ID, VERSION_ID);
     private NoneStorageManager testSubject;
 
     @BeforeEach
@@ -46,13 +48,19 @@ class NoneStorageManagerTest {
     @Test
     void testPersist() {
         Assertions.assertThrows(UnsupportedOperationException.class,
-            () -> testSubject.persist("vspId", "versionId", UPLOADED_ARTIFACT_INFO));
+            () -> testSubject.persist(VSP_ID, VERSION_ID, UPLOADED_ARTIFACT_INFO));
     }
 
     @Test
     void testUpload() {
         Assertions.assertThrows(UnsupportedOperationException.class,
-            () -> testSubject.upload("vspId", "versionId", new ByteArrayInputStream(new byte[0])));
+            () -> testSubject.upload(VSP_ID, VERSION_ID, new ByteArrayInputStream(new byte[0])));
+    }
+
+    @Test
+    void testPut() {
+        Assertions.assertThrows(UnsupportedOperationException.class,
+            () -> testSubject.put(VSP_ID, VERSION_ID, new ByteArrayInputStream(new byte[0])));
     }
 
     @Test
@@ -61,15 +69,30 @@ class NoneStorageManagerTest {
     }
 
     @Test
-    void testGet() {
+    void testGetArtifactInfo() {
         Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.get(UPLOADED_ARTIFACT_INFO));
     }
 
     @Test
-    void testDelete() {
+    void testGetString() {
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.get(VSP_ID, VERSION_ID));
+    }
+
+    @Test
+    void testDeleteArtifactInfo() {
         Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.delete(UPLOADED_ARTIFACT_INFO));
     }
 
+    @Test
+    void testDeleteString() {
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.delete(VSP_ID));
+    }
+
+    @Test
+    void testIsExists() {
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> testSubject.exists(VSP_ID));
+    }
+
     @Test
     void testIsEnabled() {
         Assertions.assertFalse(testSubject.isEnabled());
index 317bb90..5d0df22 100644 (file)
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
 
-  <parent>
-    <groupId>org.openecomp.sdc</groupId>
-    <artifactId>item-rest</artifactId>
-    <version>1.11.0-SNAPSHOT</version>
-  </parent>
+    <parent>
+        <groupId>org.openecomp.sdc</groupId>
+        <artifactId>item-rest</artifactId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
 
-  <artifactId>item-rest-services</artifactId>
+    <artifactId>item-rest-services</artifactId>
 
-  <dependencies>
-    <dependency>
-      <groupId>org.openecomp.sdc</groupId>
-      <artifactId>openecomp-sdc-item-permissions-manager</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.openecomp.sdc</groupId>
-      <artifactId>item-rest-types</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.openecomp.sdc</groupId>
-      <artifactId>openecomp-sdc-common-rest</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.httpcomponents</groupId>
-      <artifactId>httpclient</artifactId>
-      <version>${http.client.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.httpcomponents</groupId>
-          <artifactId>httpcore</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>javax.inject</groupId>
-      <artifactId>javax.inject</artifactId>
-      <version>1</version>
-    </dependency>
-    <!-- CXF -->
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
-      <version>${cxf.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.jboss.spec.javax.rmi</groupId>
-          <artifactId>jboss-rmi-api_1.0_spec</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>org.openecomp.sdc</groupId>
-      <artifactId>openecomp-sdc-conflict-manager</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-context</artifactId>
-      <exclusions>
-        <exclusion>
-          <groupId>org.springframework</groupId>
-          <artifactId>spring-expression</artifactId>
-        </exclusion>
-        <exclusion>
-          <groupId>org.springframework</groupId>
-          <artifactId>spring-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-core</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.github.tomakehurst</groupId>
-      <artifactId>wiremock-standalone</artifactId>
-      <version>${wire-mock.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.projectlombok</groupId>
-      <artifactId>lombok</artifactId>
-      <scope>provided</scope>
-    </dependency>
-  </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.openecomp.sdc</groupId>
+            <artifactId>openecomp-sdc-item-permissions-manager</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc</groupId>
+            <artifactId>item-rest-types</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc</groupId>
+            <artifactId>openecomp-sdc-common-rest</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${http.client.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpcore</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+        </dependency>
+        <!-- CXF -->
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${cxf.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.jboss.spec.javax.rmi</groupId>
+                    <artifactId>jboss-rmi-api_1.0_spec</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc</groupId>
+            <artifactId>openecomp-sdc-conflict-manager</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-expression</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.tomakehurst</groupId>
+            <artifactId>wiremock-standalone</artifactId>
+            <version>${wire-mock.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc.be</groupId>
+            <artifactId>common-be</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
 
 </project>
index f18de66..c184eca 100644 (file)
@@ -15,6 +15,8 @@
  */
 package org.openecomp.sdcrests.item.rest.services;
 
+import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
 import static org.openecomp.sdc.itempermissions.notifications.NotificationConstants.PERMISSION_USER;
 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_ID;
 import static org.openecomp.sdc.versioning.VersioningNotificationConstansts.ITEM_NAME;
@@ -36,6 +38,10 @@ import javax.inject.Named;
 import javax.ws.rs.core.Response;
 import org.openecomp.sdc.activitylog.dao.type.ActivityLogEntity;
 import org.openecomp.sdc.activitylog.dao.type.ActivityType;
+import org.openecomp.sdc.be.csar.storage.ArtifactStorageManager;
+import org.openecomp.sdc.be.csar.storage.StorageFactory;
+import org.openecomp.sdc.common.errors.ErrorCode.ErrorCodeBuilder;
+import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
 import org.openecomp.sdc.datatypes.model.ItemType;
 import org.openecomp.sdc.itempermissions.impl.types.PermissionTypes;
 import org.openecomp.sdc.logging.api.Logger;
@@ -80,13 +86,20 @@ public class ItemsImpl implements Items {
     public Response actOn(ItemActionRequestDto request, String itemId, String user) {
         Item item = getManagersProvider().getItemManager().get(itemId);
         if (item == null) {
-            return Response.status(Response.Status.NOT_FOUND).entity(new Exception("Item does not exist.")).build();
+            return Response.status(NOT_FOUND).entity(new Exception("Item does not exist.")).build();
         }
         switch (request.getAction()) {
             case ARCHIVE:
                 getManagersProvider().getItemManager().archive(item);
                 break;
             case RESTORE:
+                final var artifactStorageManager = new StorageFactory().createArtifactStorageManager();
+                if (artifactStorageManager.isEnabled() && !artifactStorageManager.exists(itemId)) {
+                    LOGGER.error("Unable to restore partially deleted item '{}'", itemId);
+                    final var errorCode =
+                        new ErrorCodeBuilder().withId(INTERNAL_SERVER_ERROR.name()).withMessage("Unable to restore partially deleted VSP, re-try VSP deletion").build();
+                    return Response.status(INTERNAL_SERVER_ERROR).entity(new ErrorCodeAndMessage(INTERNAL_SERVER_ERROR, errorCode)).build();
+                }
                 getManagersProvider().getItemManager().restore(item);
                 break;
             default:
index d7e9c81..12056ad 100644 (file)
  */
 package org.openecomp.sdcrests.item.rest.services;
 
-import static org.junit.Assert.assertEquals;
+import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.MINIO;
+import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.NONE;
 import static org.openecomp.sdcrests.item.types.ItemAction.ARCHIVE;
 import static org.openecomp.sdcrests.item.types.ItemAction.RESTORE;
 
+import io.minio.BucketExistsArgs;
+import io.minio.MinioClient;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import javax.ws.rs.core.Response;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.MockedStatic;
 import org.mockito.Mockito;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.MockitoAnnotations;
+import org.mockito.junit.jupiter.MockitoExtension;
 import org.openecomp.sdc.activitylog.ActivityLogManager;
+import org.openecomp.sdc.common.CommonConfigurationManager;
+import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
 import org.openecomp.sdc.versioning.ItemManager;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.openecomp.sdc.versioning.types.Item;
 import org.openecomp.sdcrests.item.types.ItemActionRequestDto;
 
-@RunWith(MockitoJUnitRunner.class)
-public class ItemsImplTest {
+@ExtendWith(MockitoExtension.class)
+class ItemsImplTest {
 
-    private static final String ITEM_ID = "ITEM_ID";
+    private static final String ITEM_ID = "item-id";
     private static final String USER = "USER";
+    private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
+    private static final String STORAGE_TYPE = "storageType";
+    private static final String ENDPOINT = "endpoint";
+    private static final String CREDENTIALS = "credentials";
+    private static final String TEMP_PATH = "tempPath";
+    private static final String UPLOAD_PARTSIZE = "uploadPartSize";
 
     @Mock
     private ManagersProvider managersProvider;
@@ -56,71 +83,111 @@ public class ItemsImplTest {
     private VersioningManager versioningManager;
     @Mock
     private ActivityLogManager activityManager;
+    @Mock
+    private CommonConfigurationManager commonConfigurationManager;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private MinioClient.Builder builderMinio;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private BucketExistsArgs.Builder builderBucketExistsArgs;
+
+    @InjectMocks
+    private ItemsImpl items;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+    }
 
     @Test
-    public void shouldInitActionSideAffectsMap() {
-        ItemsImpl items = new ItemsImpl();
+    void shouldInitActionSideAffectsMap() {
         items.initActionSideAffectsMap();
-        assertEquals(items.getActionSideAffectsMap().size(),2);
+        assertEquals(2, items.getActionSideAffectsMap().size());
     }
 
     @Test
-    public void shouldActOnEmptyItem() {
-        ItemsImpl items = new ItemsImpl();
+    void shouldActOnEmptyItem() {
         items.initActionSideAffectsMap();
         items.setManagersProvider(managersProvider);
-        Mockito.when(managersProvider.getItemManager()).thenReturn(itemManager);
-        Mockito.when(itemManager.get(Mockito.any())).thenReturn(null);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
+        when(itemManager.get(any())).thenReturn(null);
         Response response = items.actOn(request, ITEM_ID, USER);
         assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
     }
 
     @Test
-    public void shouldActOnARCHIVE() {
-        ItemsImpl items = new ItemsImpl();
+    void shouldActOnARCHIVE() {
         items.initActionSideAffectsMap();
         items.setManagersProvider(managersProvider);
-        Mockito.when(itemManager.get(Mockito.any())).thenReturn(item);
-        Mockito.when(request.getAction()).thenReturn(ARCHIVE);
-        Mockito.when(managersProvider.getItemManager()).thenReturn(itemManager);
-        Mockito.when(managersProvider.getVersioningManager()).thenReturn(versioningManager);
-        Mockito.when(versioningManager.list(Mockito.any())).thenReturn(getVersions());
-        Mockito.when(managersProvider.getActivityLogManager()).thenReturn(activityManager);
+        when(itemManager.get(any())).thenReturn(item);
+        when(request.getAction()).thenReturn(ARCHIVE);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
+        when(managersProvider.getVersioningManager()).thenReturn(versioningManager);
+        when(versioningManager.list(any())).thenReturn(getVersions());
+        when(managersProvider.getActivityLogManager()).thenReturn(activityManager);
         items.actOn(request, ITEM_ID, USER);
-        Mockito.verify(itemManager).archive(Mockito.any());
+        verify(itemManager).archive(any());
     }
 
     @Test
-    public void shouldActOnRESTORE() {
-        ItemsImpl items = new ItemsImpl();
+    void shouldActOnRESTORE() {
         items.initActionSideAffectsMap();
         items.setManagersProvider(managersProvider);
-        Mockito.when(itemManager.get(Mockito.any())).thenReturn(item);
-        Mockito.when(request.getAction()).thenReturn(RESTORE);
-        Mockito.when(managersProvider.getItemManager()).thenReturn(itemManager);
-        Mockito.when(managersProvider.getVersioningManager()).thenReturn(versioningManager);
-        Mockito.when(versioningManager.list(Mockito.any())).thenReturn(getVersions());
-        Mockito.when(managersProvider.getActivityLogManager()).thenReturn(activityManager);
+        when(itemManager.get(any())).thenReturn(item);
+        when(request.getAction()).thenReturn(RESTORE);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
+        when(managersProvider.getVersioningManager()).thenReturn(versioningManager);
+        when(versioningManager.list(any())).thenReturn(getVersions());
+        when(managersProvider.getActivityLogManager()).thenReturn(activityManager);
         items.actOn(request, ITEM_ID, USER);
-        Mockito.verify(itemManager).restore(Mockito.any());
+        verify(itemManager).restore(any());
+    }
+
+    @Test
+    void shouldActOnRESTORE_with_S3() throws Exception {
+        items.initActionSideAffectsMap();
+        items.setManagersProvider(managersProvider);
+        when(itemManager.get(any())).thenReturn(item);
+        when(request.getAction()).thenReturn(RESTORE);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
+        try (MockedStatic<CommonConfigurationManager> utilities = Mockito.mockStatic(CommonConfigurationManager.class)) {
+            utilities.when(CommonConfigurationManager::getInstance).thenReturn(commonConfigurationManager);
+            try (MockedStatic<MinioClient> minioUtilities = Mockito.mockStatic(MinioClient.class)) {
+                minioUtilities.when(MinioClient::builder).thenReturn(builderMinio);
+                when(commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, STORAGE_TYPE, NONE.name())).thenReturn(MINIO.name());
+                when(commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, ENDPOINT, null)).thenReturn(new HashMap<String, Object>());
+                when(commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, CREDENTIALS, null)).thenReturn(new HashMap<String, Object>());
+                when(commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, TEMP_PATH, null)).thenReturn("");
+                when(commonConfigurationManager.getConfigValue(eq(EXTERNAL_CSAR_STORE), eq(UPLOAD_PARTSIZE), anyInt())).thenReturn(0);
+                when(builderBucketExistsArgs
+                    .bucket(anyString())
+                    .build()
+                ).thenReturn(new BucketExistsArgs());
+
+                final var response = items.actOn(request, ITEM_ID, USER);
+                assertNotNull(response);
+                assertEquals(INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+                assertNotNull(response.getEntity());
+                assertTrue(response.getEntity() instanceof ErrorCodeAndMessage);
+                assertEquals(INTERNAL_SERVER_ERROR.getStatusCode(), ((ErrorCodeAndMessage) response.getEntity()).getStatus().getStatusCode());
+                assertEquals(INTERNAL_SERVER_ERROR.name(), ((ErrorCodeAndMessage) response.getEntity()).getErrorCode());
+            }
+        }
     }
 
     @Test
-    public void shouldGetItem() {
-        ItemsImpl items = new ItemsImpl();
+    void shouldGetItem() {
         items.initActionSideAffectsMap();
         items.setManagersProvider(managersProvider);
-        Mockito.when(managersProvider.getItemManager()).thenReturn(itemManager);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
         Response response = items.getItem(ITEM_ID, USER);
         assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
     }
 
     @Test
-    public void shouldList() {
-        ItemsImpl items = new ItemsImpl();
+    void shouldList() {
         items.initActionSideAffectsMap();
         items.setManagersProvider(managersProvider);
-        Mockito.when(managersProvider.getItemManager()).thenReturn(itemManager);
+        when(managersProvider.getItemManager()).thenReturn(itemManager);
         Response response = items.list(null, null, null, null, null, USER);
         assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
     }
@@ -132,4 +199,4 @@ public class ItemsImplTest {
         versions.add(new Version("3"));
         return versions;
     }
-}
\ No newline at end of file
+}