Add filesystem artifact repository implementation (#336)
Signed-off-by: Michael Hirsch <michael.hirsch@bosch-si.com>
This commit is contained in:
committed by
Kai Zimmermann
parent
9b42c8cf57
commit
8be49a1184
1
examples/hawkbit-example-app/.gitignore
vendored
1
examples/hawkbit-example-app/.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/target/
|
/target/
|
||||||
|
/artifactrepo/*
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Eclipse.IoT hawkBit - Artifact Repository MongoDB
|
||||||
|
HawkBit Artifact Repository is a library for storing binary artifacts and metadata into MongoDB.
|
||||||
|
|
||||||
|
|
||||||
|
## Using Artifact Repository MongoDB Extension
|
||||||
|
The module contains a spring-boot autoconfiguration for easily integration into spring-boot projects.
|
||||||
|
For using this extension in the hawkbit-example-application you just need to add the maven dependency.
|
||||||
|
```
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-extension-artifact-repository-mongo</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
If you do not have a mongoDB running you can use the the flapdoodle project to download and start an mongoDB on demand
|
||||||
|
```
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.flapdoodle.embed</groupId>
|
||||||
|
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||||
|
<version>${flapdoodle.version}</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<version>0.2.0-SNAPSHOT</version>
|
<version>0.2.0-SNAPSHOT</version>
|
||||||
<artifactId>hawkbit-parent</artifactId>
|
<artifactId>hawkbit-parent</artifactId>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>hawkbit-artifact-repository-mongo</artifactId>
|
<artifactId>hawkbit-extension-artifact-repository-mongo</artifactId>
|
||||||
<name>hawkBit :: Artifact Repository Mongo</name>
|
<name>hawkBit :: Artifact Repository Mongo</name>
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +70,6 @@
|
|||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Mockito -->
|
<!-- Mockito -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
@@ -44,13 +44,14 @@ import com.mongodb.gridfs.GridFSFile;
|
|||||||
* The file management which looks up all the file in the file tore.
|
* The file management which looks up all the file in the file tore.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ArtifactStore implements ArtifactRepository {
|
public class MongoDBArtifactStore implements ArtifactRepository {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactStore.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDBArtifactStore.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mongoDB field which holds the filename of the file to download. SP
|
* The mongoDB field which holds the filename of the file to download.
|
||||||
* Server uses the SHA hash as a filename and lookup in the mongoDB.
|
* hawkBit update-server uses the SHA hash as a filename and lookup in the
|
||||||
|
* mongoDB.
|
||||||
*/
|
*/
|
||||||
private static final String FILENAME = "filename";
|
private static final String FILENAME = "filename";
|
||||||
|
|
||||||
@@ -206,7 +207,7 @@ public class ArtifactStore implements ArtifactRepository {
|
|||||||
* @return a paged list of artifacts mapped from the given dbFiles
|
* @return a paged list of artifacts mapped from the given dbFiles
|
||||||
*/
|
*/
|
||||||
private List<DbArtifact> map(final List<GridFSDBFile> dbFiles) {
|
private List<DbArtifact> map(final List<GridFSDBFile> dbFiles) {
|
||||||
return dbFiles.stream().map(ArtifactStore::map).collect(Collectors.toList());
|
return dbFiles.stream().map(MongoDBArtifactStore::map).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,17 +13,16 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto configuration for the {@link ArtifactStore}.
|
* Auto configuration for the {@link MongoDBArtifactStore}.
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnMissingBean(value = ArtifactRepository.class)
|
public class MongoDBArtifactStoreAutoConfiguration {
|
||||||
public class ArtifactStoreAutoConfiguration {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Default {@link ArtifactRepository} implementation.
|
* @return Default {@link ArtifactRepository} implementation.
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public ArtifactRepository artifactRepository() {
|
public ArtifactRepository artifactRepository() {
|
||||||
return new ArtifactStore();
|
return new MongoDBArtifactStore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
# Auto Configure
|
# Auto Configure
|
||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
org.eclipse.hawkbit.artifact.repository.ArtifactStoreAutoConfiguration
|
org.eclipse.hawkbit.artifact.repository.MongoDBArtifactStoreAutoConfiguration
|
||||||
@@ -34,12 +34,12 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
@Features("Component Tests - Repository")
|
@Features("Component Tests - Repository")
|
||||||
@Stories("Artifact Store MongoDB")
|
@Stories("Artifact Store MongoDB")
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@SpringApplicationConfiguration(classes = { ArtifactStoreAutoConfiguration.class, TestConfiguration.class })
|
@SpringApplicationConfiguration(classes = { MongoDBArtifactStoreAutoConfiguration.class, TestConfiguration.class })
|
||||||
@TestPropertySource(properties = { "spring.data.mongodb.port=0", "spring.mongodb.embedded.version=3.2.7" })
|
@TestPropertySource(properties = { "spring.data.mongodb.port=0", "spring.mongodb.embedded.version=3.2.7" })
|
||||||
public class ArtifactStoreTest {
|
public class MongoDBArtifactStoreTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ArtifactStore artifactStoreUnderTest;
|
private MongoDBArtifactStore artifactStoreUnderTest;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private GridFsOperations gridFs;
|
private GridFsOperations gridFs;
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>hawkbit-extension-uaa</module>
|
<module>hawkbit-extension-uaa</module>
|
||||||
|
<module>hawkbit-extension-artifact-repository-mongo</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
1
hawkbit-artifact-repository-filesystem/.gitignore
vendored
Normal file
1
hawkbit-artifact-repository-filesystem/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/artifactrepo/*
|
||||||
17
hawkbit-artifact-repository-filesystem/README.md
Normal file
17
hawkbit-artifact-repository-filesystem/README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Eclipse.IoT hawkBit - Artifact Repository File System
|
||||||
|
|
||||||
|
This module contains the implementation of the `ArtifactRepository` based on the file-system.
|
||||||
|
It's a very convenient and easy implementation of storing the artifact binaries into the file-system based on the SHA-1 hash naming.
|
||||||
|
|
||||||
|
Due the limit of many file-systems of files within one directory, the files
|
||||||
|
are stored in different sub-directories based on the last four digits of the
|
||||||
|
SHA1-hash `/basepath/[two digit sha1]/[two digit sha1/sha1-hash-filename]`.
|
||||||
|
|
||||||
|
# Compile
|
||||||
|
|
||||||
|
#### Build hawkbit-artifact-repository-filesystem
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd hawkbit/hawkbit-artifact-repository-filesystem
|
||||||
|
$ mvn clean install
|
||||||
|
```
|
||||||
69
hawkbit-artifact-repository-filesystem/pom.xml
Normal file
69
hawkbit-artifact-repository-filesystem/pom.xml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
which accompanies this distribution, and is available at
|
||||||
|
http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
|
||||||
|
-->
|
||||||
|
<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>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-parent</artifactId>
|
||||||
|
<version>0.2.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>hawkbit-artifact-repository-filesystem</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.easytesting</groupId>
|
||||||
|
<artifactId>fest-assert-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.easytesting</groupId>
|
||||||
|
<artifactId>fest-assert</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.yandex.qatools.allure</groupId>
|
||||||
|
<artifactId>allure-junit-adaptor</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.artifact.repository;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link DbArtifact} implementation which dynamically creates a
|
||||||
|
* {@link FileInputStream} on calling {@link #getFileInputStream()}.
|
||||||
|
*/
|
||||||
|
public class ArtifactFilesystem extends DbArtifact {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
ArtifactFilesystem(final File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// suppress warning, this InputStream needs to be closed by the caller, this
|
||||||
|
// cannot be closed in this method
|
||||||
|
@SuppressWarnings("squid:S2095")
|
||||||
|
public InputStream getFileInputStream() {
|
||||||
|
try {
|
||||||
|
return new BufferedInputStream(new FileInputStream(file));
|
||||||
|
} catch (final FileNotFoundException e) {
|
||||||
|
throw Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.artifact.repository;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration properties for the file-system repository, e.g. the base-path
|
||||||
|
* to store the files.
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties("org.eclipse.hawkbit.repository.file")
|
||||||
|
public class ArtifactFilesystemProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base-path of the directory to store the artifacts.
|
||||||
|
*/
|
||||||
|
private String path = "./artifactrepo";
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(final String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.artifact.repository;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.security.DigestOutputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.io.BaseEncoding;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the {@link ArtifactRepository} to store artifacts on the
|
||||||
|
* file-system. The files are stored by their SHA1 hash of the artifact binary.
|
||||||
|
* Duplicate files with the same SHA1 hash will only stored once.
|
||||||
|
*
|
||||||
|
* All files are stored flat in one base directory configured in the
|
||||||
|
* {@link ArtifactFilesystemProperties#getPath()}.
|
||||||
|
*
|
||||||
|
* Due the limit of many file-systems of files within one directory, the files
|
||||||
|
* are stored in different sub-directories based on the last four digits of the
|
||||||
|
* SHA1-hash {@code (/basepath/[two digit sha1]/[two digit sha1])}.
|
||||||
|
*/
|
||||||
|
public class ArtifactFilesystemRepository implements ArtifactRepository {
|
||||||
|
|
||||||
|
private static final String TEMP_FILE_PREFIX = "tmp";
|
||||||
|
private static final String TEMP_FILE_SUFFIX = "artifactrepo";
|
||||||
|
private final ArtifactFilesystemProperties artifactResourceProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param artifactResourceProperties
|
||||||
|
* the properties which holds the necessary configuration for the
|
||||||
|
* file-system repository
|
||||||
|
*/
|
||||||
|
public ArtifactFilesystemRepository(final ArtifactFilesystemProperties artifactResourceProperties) {
|
||||||
|
this.artifactResourceProperties = artifactResourceProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArtifactFilesystem store(final InputStream content, final String filename, final String contentType) {
|
||||||
|
return store(content, filename, contentType, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// suppress warning, of not strong enough hashing algorithm, SHA-1 and MD5
|
||||||
|
// is not used security related
|
||||||
|
@SuppressWarnings("squid:S2070")
|
||||||
|
public ArtifactFilesystem store(final InputStream content, final String filename, final String contentType,
|
||||||
|
final DbArtifactHash hash) {
|
||||||
|
|
||||||
|
final MessageDigest mdSHA1;
|
||||||
|
final MessageDigest mdMD5;
|
||||||
|
try {
|
||||||
|
mdSHA1 = MessageDigest.getInstance("SHA1");
|
||||||
|
mdMD5 = MessageDigest.getInstance("MD5");
|
||||||
|
} catch (final NoSuchAlgorithmException e) {
|
||||||
|
throw new ArtifactStoreException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
final File file = createTempFile();
|
||||||
|
final DbArtifact artifact = store(content, contentType, hash, mdSHA1, mdMD5, file);
|
||||||
|
return renameFileToSHA1Naming(file, artifact);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteBySha1(final String sha1Hash) {
|
||||||
|
FileUtils.deleteQuietly(getFile(sha1Hash));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArtifactFilesystem getArtifactBySha1(final String sha1) {
|
||||||
|
final File file = getFile(sha1);
|
||||||
|
if (!file.exists()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final ArtifactFilesystem artifact = new ArtifactFilesystem(file);
|
||||||
|
artifact.setArtifactId(sha1);
|
||||||
|
artifact.setHashes(new DbArtifactHash(sha1, null));
|
||||||
|
artifact.setSize(file.length());
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DbArtifact store(final InputStream content, final String contentType, final DbArtifactHash hash,
|
||||||
|
final MessageDigest mdSHA1, final MessageDigest mdMD5, final File file) {
|
||||||
|
final DbArtifact artifact = new DbArtifact();
|
||||||
|
try (final DigestOutputStream outputstream = openFileOutputStream(file, mdSHA1, mdMD5)) {
|
||||||
|
final long artifactSize = ByteStreams.copy(content, outputstream);
|
||||||
|
outputstream.flush();
|
||||||
|
final String sha1Hash = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
|
||||||
|
final String md5Hash = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
|
||||||
|
artifact.setArtifactId(sha1Hash);
|
||||||
|
artifact.setSize(artifactSize);
|
||||||
|
artifact.setContentType(contentType);
|
||||||
|
artifact.setHashes(new DbArtifactHash(sha1Hash, md5Hash));
|
||||||
|
checkHashes(artifact, hash);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new ArtifactStoreException(e.getMessage(), e);
|
||||||
|
} catch (final HashNotMatchException e) {
|
||||||
|
file.delete();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArtifactFilesystem renameFileToSHA1Naming(final File file, final DbArtifact artifact) {
|
||||||
|
final File fileSHA1Naming = getFile(artifact.getHashes().getSha1());
|
||||||
|
final ArtifactFilesystem fileSystemArtifact = new ArtifactFilesystem(fileSHA1Naming);
|
||||||
|
if (fileSHA1Naming.exists()) {
|
||||||
|
FileUtils.deleteQuietly(file);
|
||||||
|
} else if (!file.renameTo(fileSHA1Naming)) {
|
||||||
|
throw new ArtifactStoreException("Could not store the file " + fileSHA1Naming);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.delete();
|
||||||
|
fileSystemArtifact.setArtifactId(artifact.getArtifactId());
|
||||||
|
fileSystemArtifact.setContentType(artifact.getContentType());
|
||||||
|
fileSystemArtifact.setHashes(artifact.getHashes());
|
||||||
|
fileSystemArtifact.setSize(artifact.getSize());
|
||||||
|
return fileSystemArtifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DbArtifact checkHashes(final DbArtifact artifact, final DbArtifactHash hash) {
|
||||||
|
if (hash == null) {
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
if (hash.getSha1() != null && !artifact.getHashes().getSha1().equals(hash.getSha1())) {
|
||||||
|
throw new HashNotMatchException("The given sh1 hash " + hash.getSha1()
|
||||||
|
+ " does not match with the calcualted sha1 hash " + artifact.getHashes().getSha1(),
|
||||||
|
HashNotMatchException.SHA1);
|
||||||
|
}
|
||||||
|
if (hash.getMd5() != null && !artifact.getHashes().getMd5().equals(hash.getMd5())) {
|
||||||
|
throw new HashNotMatchException("The given md5 hash " + hash.getMd5()
|
||||||
|
+ " does not match with the calcualted md5 hash " + artifact.getHashes().getMd5(),
|
||||||
|
HashNotMatchException.MD5);
|
||||||
|
}
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File createTempFile() {
|
||||||
|
try {
|
||||||
|
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new ArtifactStoreException("Cannot create tempfile", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getFile(final String sha1) {
|
||||||
|
final File aritfactDirectory = getSha1DirectoryPath(sha1).toFile();
|
||||||
|
aritfactDirectory.mkdirs();
|
||||||
|
return new File(aritfactDirectory, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path getSha1DirectoryPath(final String sha1) {
|
||||||
|
final int length = sha1.length();
|
||||||
|
final List<String> folders = Splitter.fixedLength(2).splitToList(sha1.substring(length - 4, length));
|
||||||
|
final String folder1 = folders.get(0);
|
||||||
|
final String folder2 = folders.get(1);
|
||||||
|
return Paths.get(artifactResourceProperties.getPath(), folder1, folder2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DigestOutputStream openFileOutputStream(final File file, final MessageDigest mdSHA1,
|
||||||
|
final MessageDigest mdMD5) throws FileNotFoundException {
|
||||||
|
return new DigestOutputStream(
|
||||||
|
new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(file)), mdMD5), mdSHA1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.artifact.repository;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
|
import org.fest.assertions.api.Assertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
|
|
||||||
|
@Features("Unit Tests - Artifact File System Repository")
|
||||||
|
@Stories("Test storing artifact binaries in the file-system")
|
||||||
|
public class ArtifactFilesystemRepositoryTest {
|
||||||
|
|
||||||
|
private final ArtifactFilesystemProperties artifactResourceProperties = new ArtifactFilesystemProperties();
|
||||||
|
|
||||||
|
private final ArtifactFilesystemRepository artifactFilesystemRepository = new ArtifactFilesystemRepository(
|
||||||
|
artifactResourceProperties);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that an artifact can be successfully stored in the file-system repository")
|
||||||
|
public void storeSuccessfully() throws IOException {
|
||||||
|
final byte[] fileContent = randomBytes();
|
||||||
|
final ArtifactFilesystem artifact = storeRandomArtifact(fileContent);
|
||||||
|
|
||||||
|
final byte[] readContent = new byte[fileContent.length];
|
||||||
|
IOUtils.read(artifact.getFileInputStream(), readContent);
|
||||||
|
|
||||||
|
assertThat(readContent).isEqualTo(fileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that an artifact can be successfully stored in the file-system repository")
|
||||||
|
public void getStoredArtifactBasedOnSHA1Hash() {
|
||||||
|
|
||||||
|
final byte[] fileContent = randomBytes();
|
||||||
|
final ArtifactFilesystem artifact = storeRandomArtifact(fileContent);
|
||||||
|
|
||||||
|
final DbArtifact artifactBySha1 = artifactFilesystemRepository
|
||||||
|
.getArtifactBySha1(artifact.getHashes().getSha1());
|
||||||
|
assertThat(artifactBySha1).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that an artifact can be deleted in the file-system repository")
|
||||||
|
public void deleteStoredArtifactBySHA1Hash() {
|
||||||
|
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
|
||||||
|
|
||||||
|
artifactFilesystemRepository.deleteBySha1(artifact.getHashes().getSha1());
|
||||||
|
|
||||||
|
assertThat(artifactFilesystemRepository.getArtifactBySha1(artifact.getHashes().getSha1())).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verfies that an artifact which does not exists is deleted quietly in the file-system repository")
|
||||||
|
public void deleteArtifactWhichDoesNotExistsBySHA1HashWithoutException() {
|
||||||
|
try {
|
||||||
|
artifactFilesystemRepository.deleteBySha1("sha1HashWhichDoesNotExists");
|
||||||
|
} catch (final Exception e) {
|
||||||
|
Assertions.fail("did not expect an exception while deleting a file which does not exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArtifactFilesystem storeRandomArtifact(final byte[] fileContent) {
|
||||||
|
final String fileName = "filename.tmp";
|
||||||
|
final ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContent);
|
||||||
|
final ArtifactFilesystem store = artifactFilesystemRepository.store(inputStream, fileName, "application/txt");
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] randomBytes() {
|
||||||
|
final byte[] randomBytes = new byte[20];
|
||||||
|
final Random ran = new Random();
|
||||||
|
ran.nextBytes(randomBytes);
|
||||||
|
return randomBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.artifact.repository;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.fest.assertions.api.Assertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
|
|
||||||
|
@Features("Unit Tests - Artifact File System Repository")
|
||||||
|
@Stories("Test storing artifact binaries in the file-system")
|
||||||
|
public class ArtifactFilesystemTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that an exception is thrown on opening an InputStream when file does not exists")
|
||||||
|
public void getInputStreamOfNonExistingFileThrowsException() {
|
||||||
|
final File file = new File("fileWhichTotalDoesNotExists");
|
||||||
|
final ArtifactFilesystem underTest = new ArtifactFilesystem(file);
|
||||||
|
try {
|
||||||
|
underTest.getFileInputStream();
|
||||||
|
Assertions.fail("Expected a FileNotFoundException because file does not exists");
|
||||||
|
} catch (final RuntimeException e) {
|
||||||
|
assertThat(e.getCause()).isInstanceOf(FileNotFoundException.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that an InputStream can be opened if file exists")
|
||||||
|
public void getInputStreamOfExistingFile() throws IOException {
|
||||||
|
final File createTempFile = File.createTempFile(ArtifactFilesystemTest.class.getSimpleName(), "");
|
||||||
|
createTempFile.deleteOnExit();
|
||||||
|
|
||||||
|
final ArtifactFilesystem underTest = new ArtifactFilesystem(createTempFile);
|
||||||
|
final byte[] buffer = new byte[1024];
|
||||||
|
IOUtils.read(underTest.getFileInputStream(), buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# HawkBit Artifact Repositoy
|
|
||||||
HawkBit Artifact Repository is library for storing binary artifacts and metadata into MongoDB.
|
|
||||||
It has an spring-boot autoconfiguration for easily integration into spring-boot projects.
|
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
http://www.eclipse.org/legal/epl-v10.html
|
http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<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">
|
||||||
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
@@ -68,6 +67,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
|
<artifactId>hawkbit-artifact-repository-filesystem</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-context-support</artifactId>
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.autoconfigure.repository;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactFilesystemProperties;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactFilesystemRepository;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto configuration for the {@link ArtifactFilesystemRepository}.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(ArtifactRepository.class)
|
||||||
|
@EnableConfigurationProperties(ArtifactFilesystemProperties.class)
|
||||||
|
public class ArtifactStoreAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param artifactFilesystemProperties
|
||||||
|
* the artifact file system properties
|
||||||
|
* @return Default {@link ArtifactRepository} implementation.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public ArtifactRepository artifactRepository(final ArtifactFilesystemProperties artifactFilesystemProperties) {
|
||||||
|
return new ArtifactFilesystemRepository(artifactFilesystemProperties);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,4 +11,5 @@ org.eclipse.hawkbit.autoconfigure.event.EventPublisherAutoConfiguration,\
|
|||||||
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
|
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
|
||||||
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
|
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
|
||||||
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration,\
|
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration,\
|
||||||
org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementConfiguration
|
org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementConfiguration,\
|
||||||
|
org.eclipse.hawkbit.autoconfigure.repository.ArtifactStoreAutoConfiguration
|
||||||
|
|||||||
@@ -133,11 +133,6 @@
|
|||||||
<artifactId>fest-assert</artifactId>
|
<artifactId>fest-assert</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ru.yandex.qatools.allure</groupId>
|
<groupId>ru.yandex.qatools.allure</groupId>
|
||||||
<artifactId>allure-junit-adaptor</artifactId>
|
<artifactId>allure-junit-adaptor</artifactId>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import org.eclipse.hawkbit.repository.model.Artifact;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||||
@@ -62,7 +62,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
@Features("Component Tests - Direct Device Integration API")
|
@Features("Component Tests - Direct Device Integration API")
|
||||||
@Stories("Artifact Download Resource")
|
@Stories("Artifact Download Resource")
|
||||||
@SpringApplicationConfiguration(classes = DownloadTestConfiguration.class)
|
@SpringApplicationConfiguration(classes = DownloadTestConfiguration.class)
|
||||||
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB {
|
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTest {
|
||||||
|
|
||||||
private static final int ARTIFACT_SIZE = 5 * 1024 * 1024;
|
private static final int ARTIFACT_SIZE = 5 * 1024 * 1024;
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
|||||||
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
import org.fest.assertions.core.Condition;
|
import org.fest.assertions.core.Condition;
|
||||||
@@ -59,7 +59,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
*/
|
*/
|
||||||
@Features("Component Tests - Direct Device Integration API")
|
@Features("Component Tests - Direct Device Integration API")
|
||||||
@Stories("Deployment Action Resource")
|
@Stories("Deployment Action Resource")
|
||||||
public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoDB {
|
public class DdiDeploymentBaseTest extends AbstractRestIntegrationTest {
|
||||||
|
|
||||||
private static final String HTTP_LOCALHOST = "http://localhost:8080/";
|
private static final String HTTP_LOCALHOST = "http://localhost:8080/";
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
|||||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||||
@@ -57,7 +57,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
*/
|
*/
|
||||||
@Features("Component Tests - Direct Device Integration API")
|
@Features("Component Tests - Direct Device Integration API")
|
||||||
@Stories("Root Poll Resource")
|
@Stories("Root Poll Resource")
|
||||||
public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoDB {
|
public class DdiRootControllerTest extends AbstractRestIntegrationTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HawkbitSecurityProperties securityProperties;
|
private HawkbitSecurityProperties securityProperties;
|
||||||
|
|||||||
@@ -137,11 +137,6 @@
|
|||||||
<artifactId>fest-assert</artifactId>
|
<artifactId>fest-assert</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-config</artifactId>
|
<artifactId>spring-security-config</artifactId>
|
||||||
|
|||||||
@@ -131,11 +131,6 @@
|
|||||||
<artifactId>fest-assert</artifactId>
|
<artifactId>fest-assert</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ru.yandex.qatools.allure</groupId>
|
<groupId>ru.yandex.qatools.allure</groupId>
|
||||||
<artifactId>allure-junit-adaptor</artifactId>
|
<artifactId>allure-junit-adaptor</artifactId>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
package org.eclipse.hawkbit.mgmt.rest.resource;
|
package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
@@ -82,8 +83,8 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
|
|||||||
artifactCache.getId(), artifactCache.getDownloadType());
|
artifactCache.getId(), artifactCache.getDownloadType());
|
||||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
try {
|
try (InputStream inputstream = artifact.getFileInputStream()) {
|
||||||
ByteStreams.copy(artifact.getFileInputStream(),
|
ByteStreams.copy(inputstream,
|
||||||
requestResponseContextHolder.getHttpServletResponse().getOutputStream());
|
requestResponseContextHolder.getHttpServletResponse().getOutputStream());
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
LOGGER.error("Cannot copy streams", e);
|
LOGGER.error("Cannot copy streams", e);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
|||||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -30,7 +30,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
|
|
||||||
@Features("Component Tests - Management API")
|
@Features("Component Tests - Management API")
|
||||||
@Stories("Download Resource")
|
@Stories("Download Resource")
|
||||||
public class MgmtDownloadResourceTest extends AbstractRestIntegrationTestWithMongoDB {
|
public class MgmtDownloadResourceTest extends AbstractRestIntegrationTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DownloadIdCache downloadIdCache;
|
private DownloadIdCache downloadIdCache;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -43,7 +44,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||||
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
|
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||||
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
||||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
@@ -70,7 +71,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
*/
|
*/
|
||||||
@Features("Component Tests - Management API")
|
@Features("Component Tests - Management API")
|
||||||
@Stories("Software Module Resource")
|
@Stories("Software Module Resource")
|
||||||
public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestWithMongoDB {
|
public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void assertPreparationOfRepo() {
|
public void assertPreparationOfRepo() {
|
||||||
@@ -165,12 +166,12 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
|||||||
assertThat(artifactManagement.countArtifactsAll()).as("Wrong artifact size").isEqualTo(1);
|
assertThat(artifactManagement.countArtifactsAll()).as("Wrong artifact size").isEqualTo(1);
|
||||||
|
|
||||||
// binary
|
// binary
|
||||||
|
try (InputStream fileInputStream = artifactManagement
|
||||||
|
.loadArtifactBinary(softwareManagement.findSoftwareModuleById(sm.getId()).getArtifacts().get(0))
|
||||||
|
.getFileInputStream()) {
|
||||||
assertTrue("Wrong artifact content",
|
assertTrue("Wrong artifact content",
|
||||||
IOUtils.contentEquals(new ByteArrayInputStream(random),
|
IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream));
|
||||||
artifactManagement
|
}
|
||||||
.loadArtifactBinary(
|
|
||||||
softwareManagement.findSoftwareModuleById(sm.getId()).getArtifacts().get(0))
|
|
||||||
.getFileInputStream()));
|
|
||||||
|
|
||||||
// hashes
|
// hashes
|
||||||
assertThat(artifactManagement.findArtifactByFilename("origFilename").get(0).getSha1Hash()).as("Wrong sha1 hash")
|
assertThat(artifactManagement.findArtifactByFilename("origFilename").get(0).getSha1Hash()).as("Wrong sha1 hash")
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.mgmt.rest.resource;
|
|
||||||
|
|
||||||
import static org.fest.assertions.api.Assertions.assertThat;
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
|
||||||
import org.eclipse.hawkbit.exception.SpServerError;
|
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|
||||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
|
||||||
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Description;
|
|
||||||
import ru.yandex.qatools.allure.annotations.Features;
|
|
||||||
import ru.yandex.qatools.allure.annotations.Stories;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link MgmtSoftwareModuleResource} in case of missing MongoDB
|
|
||||||
* connection.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Features("Component Tests - Management API")
|
|
||||||
@Stories("Download Resource")
|
|
||||||
public class SMRessourceMisingMongoDbConnectionTest extends AbstractRestIntegrationTestWithMongoDB {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Description("Ensures that the correct error code is returned in case MongoDB unavailable.")
|
|
||||||
public void missingMongoDbConnectionResultsInErrorAtUpload() throws Exception {
|
|
||||||
mongodExecutable.stop();
|
|
||||||
|
|
||||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
|
||||||
assertThat(artifactManagement.countArtifactsAll()).isEqualTo(0);
|
|
||||||
SoftwareModule sm = entityFactory.generateSoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"),
|
|
||||||
"name 1", "version 1", null, null);
|
|
||||||
sm = softwareManagement.createSoftwareModule(sm);
|
|
||||||
assertThat(artifactManagement.countArtifactsAll()).isEqualTo(0);
|
|
||||||
|
|
||||||
// create test file
|
|
||||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
|
||||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random);
|
|
||||||
|
|
||||||
// upload
|
|
||||||
final MvcResult mvcResult = mvc
|
|
||||||
.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file))
|
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isInternalServerError()).andReturn();
|
|
||||||
|
|
||||||
// check error result
|
|
||||||
final ExceptionInfo exceptionInfo = ResourceUtility
|
|
||||||
.convertException(mvcResult.getResponse().getContentAsString());
|
|
||||||
assertThat(exceptionInfo.getErrorCode()).isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED.getKey());
|
|
||||||
assertThat(exceptionInfo.getMessage()).isEqualTo(SpServerError.SP_ARTIFACT_UPLOAD_FAILED.getMessage());
|
|
||||||
|
|
||||||
// ensure that the JPA transaction was rolled back
|
|
||||||
assertThat(artifactManagement.countArtifactsAll()).isEqualTo(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void cleanCurrentCollection() {
|
|
||||||
// not needed, mongodb is stopped already
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-artifact-repository-mongo</artifactId>
|
<artifactId>hawkbit-artifact-repository-filesystem</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -20,12 +20,10 @@ import javax.persistence.Table;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
|
|
||||||
import com.mongodb.gridfs.GridFS;
|
|
||||||
import com.mongodb.gridfs.GridFSFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA implementation of {@link LocalArtifact}.
|
* JPA implementation of {@link LocalArtifact}.
|
||||||
*
|
*
|
||||||
@@ -73,9 +71,9 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art
|
|||||||
* Constructs artifact.
|
* Constructs artifact.
|
||||||
*
|
*
|
||||||
* @param gridFsFileName
|
* @param gridFsFileName
|
||||||
* that is the link to the {@link GridFS} entity.
|
* that is the link to the {@link DbArtifact} entity.
|
||||||
* @param filename
|
* @param filename
|
||||||
* that is used by {@link GridFSFile} store.
|
* that is used by {@link DbArtifact} store.
|
||||||
* @param softwareModule
|
* @param softwareModule
|
||||||
* of this artifact
|
* of this artifact
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
|||||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
|
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||||
import org.springframework.data.mongodb.gridfs.GridFsOperations;
|
|
||||||
|
|
||||||
@SpringApplicationConfiguration(classes = { org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
|
@SpringApplicationConfiguration(classes = { org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
|
||||||
public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest {
|
public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest {
|
||||||
@@ -62,9 +61,6 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected TargetInfoRepository targetInfoRepository;
|
protected TargetInfoRepository targetInfoRepository;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected GridFsOperations operations;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected RolloutGroupRepository rolloutGroupRepository;
|
protected RolloutGroupRepository rolloutGroupRepository;
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.repository.jpa;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.persistence.PersistenceContext;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
|
||||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
|
||||||
|
|
||||||
@SpringApplicationConfiguration(classes = { org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
|
|
||||||
public abstract class AbstractJpaIntegrationTestWithMongoDB extends AbstractIntegrationTest {
|
|
||||||
|
|
||||||
@PersistenceContext
|
|
||||||
protected EntityManager entityManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected TargetRepository targetRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected ActionRepository actionRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected DistributionSetRepository distributionSetRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected SoftwareModuleRepository softwareModuleRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected TenantMetaDataRepository tenantMetaDataRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected DistributionSetTypeRepository distributionSetTypeRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected SoftwareModuleTypeRepository softwareModuleTypeRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected TargetTagRepository targetTagRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected DistributionSetTagRepository distributionSetTagRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected SoftwareModuleMetadataRepository softwareModuleMetadataRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected ActionStatusRepository actionStatusRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected LocalArtifactRepository artifactRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected TargetInfoRepository targetInfoRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected RolloutGroupRepository rolloutGroupRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected RolloutRepository rolloutRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected TenantAwareCacheManager cacheManager;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.repository.jpa;
|
|
||||||
|
|
||||||
import static org.fest.assertions.api.Assertions.assertThat;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException;
|
|
||||||
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Description;
|
|
||||||
import ru.yandex.qatools.allure.annotations.Features;
|
|
||||||
import ru.yandex.qatools.allure.annotations.Stories;
|
|
||||||
|
|
||||||
@Features("Component Tests - Repository")
|
|
||||||
@Stories("Artifact Management")
|
|
||||||
public class ArtifactManagementFailedMongoDBTest extends AbstractJpaIntegrationTestWithMongoDB {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Description("Trys and fails to delete or create local artifact with a down mongodb and checks if expected ArtifactDeleteFailedException is thrown.")
|
|
||||||
public void deleteArtifactsWithNoMongoDb() throws UnknownHostException, IOException {
|
|
||||||
// ensure baseline
|
|
||||||
assertThat(artifactRepository.findAll()).isEmpty();
|
|
||||||
|
|
||||||
// prepare test
|
|
||||||
JpaSoftwareModule sm = new JpaSoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"), "name 1",
|
|
||||||
"version 1", null, null);
|
|
||||||
sm = softwareModuleRepository.save(sm);
|
|
||||||
|
|
||||||
final Artifact result = artifactManagement.createArtifact(new RandomGeneratedInputStream(5 * 1024), sm.getId(),
|
|
||||||
"file1", false);
|
|
||||||
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
|
||||||
|
|
||||||
mongodExecutable.stop();
|
|
||||||
try {
|
|
||||||
artifactManagement.deleteArtifact(result.getId());
|
|
||||||
fail("deletion should have failed");
|
|
||||||
} catch (final ArtifactDeleteFailedException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
artifactManagement.createArtifact(new RandomGeneratedInputStream(5 * 1024), sm.getId(), "file2", false);
|
|
||||||
fail("Should not have worked with MongoDb down.");
|
|
||||||
} catch (final ArtifactUploadFailedException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void cleanCurrentCollection() {
|
|
||||||
// no need to clean, is stopped already
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,7 @@ import static org.junit.Assert.fail;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
@@ -28,8 +29,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|||||||
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
|
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Description;
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
import ru.yandex.qatools.allure.annotations.Features;
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
@@ -44,7 +43,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
*/
|
*/
|
||||||
@Features("Component Tests - Repository")
|
@Features("Component Tests - Repository")
|
||||||
@Stories("Artifact Management")
|
@Stories("Artifact Management")
|
||||||
public class ArtifactManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
|
public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for
|
* Test method for
|
||||||
@@ -151,25 +150,17 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
assertThat(result2.getId()).isNotNull();
|
assertThat(result2.getId()).isNotNull();
|
||||||
assertThat(((JpaArtifact) result).getGridFsFileName())
|
assertThat(((JpaArtifact) result).getGridFsFileName())
|
||||||
.isNotEqualTo(((JpaArtifact) result2).getGridFsFileName());
|
.isNotEqualTo(((JpaArtifact) result2).getGridFsFileName());
|
||||||
assertThat(operations.findOne(
|
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNotNull();
|
||||||
.isNotNull();
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getGridFsFileName())).isNotNull();
|
||||||
assertThat(operations.findOne(
|
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result2).getGridFsFileName()))))
|
|
||||||
.isNotNull();
|
|
||||||
|
|
||||||
artifactManagement.deleteArtifact(result.getId());
|
artifactManagement.deleteArtifact(result.getId());
|
||||||
assertThat(operations.findOne(
|
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNull();
|
||||||
.isNull();
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getGridFsFileName())).isNotNull();
|
||||||
assertThat(operations.findOne(
|
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result2).getGridFsFileName()))))
|
|
||||||
.isNotNull();
|
|
||||||
|
|
||||||
artifactManagement.deleteArtifact(result2.getId());
|
artifactManagement.deleteArtifact(result2.getId());
|
||||||
assertThat(operations.findOne(
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result2).getGridFsFileName())).isNull();
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result2).getGridFsFileName()))))
|
|
||||||
.isNull();
|
|
||||||
|
|
||||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||||
}
|
}
|
||||||
@@ -198,18 +189,12 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
assertThat(result2.getId()).isNotNull();
|
assertThat(result2.getId()).isNotNull();
|
||||||
assertThat(((JpaArtifact) result).getGridFsFileName()).isEqualTo(((JpaArtifact) result2).getGridFsFileName());
|
assertThat(((JpaArtifact) result).getGridFsFileName()).isEqualTo(((JpaArtifact) result2).getGridFsFileName());
|
||||||
|
|
||||||
assertThat(operations.findOne(
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNotNull();
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
|
||||||
.isNotNull();
|
|
||||||
artifactManagement.deleteArtifact(result.getId());
|
artifactManagement.deleteArtifact(result.getId());
|
||||||
assertThat(operations.findOne(
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNotNull();
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
|
||||||
.isNotNull();
|
|
||||||
|
|
||||||
artifactManagement.deleteArtifact(result2.getId());
|
artifactManagement.deleteArtifact(result2.getId());
|
||||||
assertThat(operations.findOne(
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNull();
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
|
||||||
.isNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,8 +238,10 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
final Artifact result = artifactManagement.createArtifact(new ByteArrayInputStream(random), sm.getId(), "file1",
|
final Artifact result = artifactManagement.createArtifact(new ByteArrayInputStream(random), sm.getId(), "file1",
|
||||||
false);
|
false);
|
||||||
|
|
||||||
assertTrue("The stored binary matches the given binary", IOUtils.contentEquals(new ByteArrayInputStream(random),
|
try (InputStream fileInputStream = artifactManagement.loadArtifactBinary(result).getFileInputStream()) {
|
||||||
artifactManagement.loadArtifactBinary(result).getFileInputStream()));
|
assertTrue("The stored binary matches the given binary",
|
||||||
|
IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ import org.eclipse.hawkbit.repository.test.util.WithUser;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.mongodb.core.query.Criteria;
|
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
@@ -57,7 +55,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
|
|
||||||
@Features("Component Tests - Repository")
|
@Features("Component Tests - Repository")
|
||||||
@Stories("Software Management")
|
@Stories("Software Management")
|
||||||
public class SoftwareManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
|
public class SoftwareManagementTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Try to update non updatable fields results in repository doing nothing.")
|
@Description("Try to update non updatable fields results in repository doing nothing.")
|
||||||
@@ -467,9 +465,6 @@ public class SoftwareManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
@Description("Delete an softwaremodule with an artifact, which is alsoused by another softwaremodule.")
|
@Description("Delete an softwaremodule with an artifact, which is alsoused by another softwaremodule.")
|
||||||
public void deleteSoftwareModulesWithSharedArtifact() throws IOException {
|
public void deleteSoftwareModulesWithSharedArtifact() throws IOException {
|
||||||
|
|
||||||
// Precondition: Make sure MongoDB is Empty
|
|
||||||
assertThat(operations.find(new Query())).hasSize(0);
|
|
||||||
|
|
||||||
// Init artifact binary data, target and DistributionSets
|
// Init artifact binary data, target and DistributionSets
|
||||||
final byte[] source = RandomUtils.nextBytes(1024);
|
final byte[] source = RandomUtils.nextBytes(1024);
|
||||||
|
|
||||||
@@ -489,9 +484,6 @@ public class SoftwareManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
moduleY = softwareManagement.findSoftwareModuleById(moduleY.getId());
|
moduleY = softwareManagement.findSoftwareModuleById(moduleY.getId());
|
||||||
final Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
final Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
||||||
|
|
||||||
// verify: that only one entry was created in mongoDB
|
|
||||||
assertThat(operations.find(new Query())).hasSize(1);
|
|
||||||
|
|
||||||
// [STEP5]: Delete SoftwareModuleX
|
// [STEP5]: Delete SoftwareModuleX
|
||||||
softwareManagement.deleteSoftwareModule(moduleX.getId());
|
softwareManagement.deleteSoftwareModule(moduleX.getId());
|
||||||
|
|
||||||
@@ -515,9 +507,6 @@ public class SoftwareManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
@Description("Delete two assigned softwaremodules which share an artifact.")
|
@Description("Delete two assigned softwaremodules which share an artifact.")
|
||||||
public void deleteMultipleSoftwareModulesWhichShareAnArtifact() throws IOException {
|
public void deleteMultipleSoftwareModulesWhichShareAnArtifact() throws IOException {
|
||||||
|
|
||||||
// Precondition: Make sure MongoDB is Empty
|
|
||||||
assertThat(operations.find(new Query())).hasSize(0);
|
|
||||||
|
|
||||||
// Init artifact binary data, target and DistributionSets
|
// Init artifact binary data, target and DistributionSets
|
||||||
final byte[] source = RandomUtils.nextBytes(1024);
|
final byte[] source = RandomUtils.nextBytes(1024);
|
||||||
final Target target = targetManagement.createTarget(new JpaTarget("test123"));
|
final Target target = targetManagement.createTarget(new JpaTarget("test123"));
|
||||||
@@ -540,9 +529,6 @@ public class SoftwareManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
moduleY = softwareManagement.findSoftwareModuleById(moduleY.getId());
|
moduleY = softwareManagement.findSoftwareModuleById(moduleY.getId());
|
||||||
final Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
final Artifact artifactY = moduleY.getArtifacts().iterator().next();
|
||||||
|
|
||||||
// verify: that only one entry was created in mongoDB
|
|
||||||
assertThat(operations.find(new Query())).hasSize(1);
|
|
||||||
|
|
||||||
// [STEP3]: Assign SoftwareModuleX to DistributionSetX and to target
|
// [STEP3]: Assign SoftwareModuleX to DistributionSetX and to target
|
||||||
distributionSetManagement.assignSoftwareModules(disSetX, Sets.newHashSet(moduleX));
|
distributionSetManagement.assignSoftwareModules(disSetX, Sets.newHashSet(moduleX));
|
||||||
deploymentManagement.assignDistributionSet(disSetX, Lists.newArrayList(target));
|
deploymentManagement.assignDistributionSet(disSetX, Lists.newArrayList(target));
|
||||||
@@ -611,17 +597,14 @@ public class SoftwareManagementTest extends AbstractJpaIntegrationTestWithMongoD
|
|||||||
assertThat(artifactRepository.findAll()).hasSize(results.length);
|
assertThat(artifactRepository.findAll()).hasSize(results.length);
|
||||||
for (final Artifact result : results) {
|
for (final Artifact result : results) {
|
||||||
assertThat(result.getId()).isNotNull();
|
assertThat(result.getId()).isNotNull();
|
||||||
assertThat(operations.findOne(
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName()))
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
|
||||||
.isNotNull();
|
.isNotNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertArtfiactNull(final Artifact... results) {
|
private void assertArtfiactNull(final Artifact... results) {
|
||||||
for (final Artifact result : results) {
|
for (final Artifact result : results) {
|
||||||
assertThat(operations.findOne(
|
assertThat(binaryArtifactRepository.getArtifactBySha1(((JpaArtifact) result).getGridFsFileName())).isNull();
|
||||||
new Query().addCriteria(Criteria.where("filename").is(((JpaArtifact) result).getGridFsFileName()))))
|
|
||||||
.isNull();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
|
|
||||||
@Features("Component Tests - Repository")
|
@Features("Component Tests - Repository")
|
||||||
@Stories("System Management")
|
@Stories("System Management")
|
||||||
public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
|
public class SystemManagementTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in")
|
@Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in")
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
|
|
||||||
@Features("Component Tests - Repository")
|
@Features("Component Tests - Repository")
|
||||||
@Stories("Tenant Configuration Management")
|
@Stories("Tenant Configuration Management")
|
||||||
public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
|
public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests that tenant specific configuration can be persisted and in case the tenant does not have specific configuration the default from environment is used instead.")
|
@Description("Tests that tenant specific configuration can be persisted and in case the tenant does not have specific configuration the default from environment is used instead.")
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-artifact-repository-mongo</artifactId>
|
<artifactId>hawkbit-artifact-repository-filesystem</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -43,8 +43,8 @@
|
|||||||
<artifactId>spring-context-support</artifactId>
|
<artifactId>spring-context-support</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
<artifactId>spring-tx</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net._01001111</groupId>
|
<groupId>net._01001111</groupId>
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import java.util.concurrent.Executors;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties;
|
import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties;
|
||||||
import org.eclipse.hawkbit.api.PropertyBasedArtifactUrlHandler;
|
import org.eclipse.hawkbit.api.PropertyBasedArtifactUrlHandler;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactFilesystemProperties;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactFilesystemRepository;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||||
import org.eclipse.hawkbit.cache.DefaultDownloadIdCache;
|
import org.eclipse.hawkbit.cache.DefaultDownloadIdCache;
|
||||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||||
@@ -53,7 +56,6 @@ import org.springframework.security.concurrent.DelegatingSecurityContextExecutor
|
|||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
|
||||||
import com.mongodb.MongoClientOptions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring context configuration required for Dev.Environment.
|
* Spring context configuration required for Dev.Environment.
|
||||||
@@ -64,10 +66,16 @@ import com.mongodb.MongoClientOptions;
|
|||||||
@Configuration
|
@Configuration
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.PROXY, proxyTargetClass = false, securedEnabled = true)
|
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.PROXY, proxyTargetClass = false, securedEnabled = true)
|
||||||
@EnableConfigurationProperties({ HawkbitServerProperties.class, DdiSecurityProperties.class,
|
@EnableConfigurationProperties({ HawkbitServerProperties.class, DdiSecurityProperties.class,
|
||||||
ArtifactUrlHandlerProperties.class })
|
ArtifactUrlHandlerProperties.class, ArtifactFilesystemProperties.class })
|
||||||
@Profile("test")
|
@Profile("test")
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
public class TestConfiguration implements AsyncConfigurer {
|
public class TestConfiguration implements AsyncConfigurer {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ArtifactRepository artifactRepository(final ArtifactFilesystemProperties artifactFilesystemProperties) {
|
||||||
|
return new ArtifactFilesystemRepository(artifactFilesystemProperties);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TestRepositoryManagement testRepositoryManagement(final SystemSecurityContext systemSecurityContext,
|
public TestRepositoryManagement testRepositoryManagement(final SystemSecurityContext systemSecurityContext,
|
||||||
final SystemManagement systemManagement) {
|
final SystemManagement systemManagement) {
|
||||||
@@ -85,13 +93,6 @@ public class TestConfiguration implements AsyncConfigurer {
|
|||||||
return new PropertyBasedArtifactUrlHandler(urlHandlerProperties);
|
return new PropertyBasedArtifactUrlHandler(urlHandlerProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MongoClientOptions options() {
|
|
||||||
return MongoClientOptions.builder().connectTimeout(500).maxWaitTime(500).connectionsPerHost(2)
|
|
||||||
.serverSelectionTimeout(500).build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TenantAware tenantAware() {
|
public TenantAware tenantAware() {
|
||||||
return new SecurityContextTenantAware();
|
return new SecurityContextTenantAware();
|
||||||
|
|||||||
@@ -12,8 +12,15 @@ import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpre
|
|||||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
|
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
|
||||||
import static org.junit.rules.RuleChain.outerRule;
|
import static org.junit.rules.RuleChain.outerRule;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
|
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
|
||||||
import org.eclipse.hawkbit.TestConfiguration;
|
import org.eclipse.hawkbit.TestConfiguration;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactFilesystemProperties;
|
||||||
|
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||||
|
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
@@ -54,13 +61,10 @@ import org.springframework.core.env.Environment;
|
|||||||
import org.springframework.data.auditing.AuditingHandler;
|
import org.springframework.data.auditing.AuditingHandler;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
|
||||||
import org.springframework.data.mongodb.gridfs.GridFsOperations;
|
|
||||||
import org.springframework.hateoas.MediaTypes;
|
import org.springframework.hateoas.MediaTypes;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.TestPropertySource;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
@@ -68,8 +72,6 @@ import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
|||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
import de.flapdoodle.embed.mongo.MongodExecutable;
|
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@WebAppConfiguration
|
@WebAppConfiguration
|
||||||
@ActiveProfiles({ "test" })
|
@ActiveProfiles({ "test" })
|
||||||
@@ -80,7 +82,6 @@ import de.flapdoodle.embed.mongo.MongodExecutable;
|
|||||||
// refreshed we e.g. get two instances of CacheManager which leads to very
|
// refreshed we e.g. get two instances of CacheManager which leads to very
|
||||||
// strange test failures.
|
// strange test failures.
|
||||||
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
|
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
|
||||||
@TestPropertySource(properties = { "spring.data.mongodb.port=0", "spring.mongodb.embedded.version=3.2.7" })
|
|
||||||
public abstract class AbstractIntegrationTest implements EnvironmentAware {
|
public abstract class AbstractIntegrationTest implements EnvironmentAware {
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class);
|
private final static Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class);
|
||||||
|
|
||||||
@@ -154,6 +155,15 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected SystemSecurityContext systemSecurityContext;
|
protected SystemSecurityContext systemSecurityContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ArtifactFilesystemProperties artifactFilesystemProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected ArtifactRepository binaryArtifactRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected TenantAwareCacheManager cacheManager;
|
||||||
|
|
||||||
protected MockMvc mvc;
|
protected MockMvc mvc;
|
||||||
|
|
||||||
protected SoftwareModuleType osType;
|
protected SoftwareModuleType osType;
|
||||||
@@ -165,12 +175,6 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected TestdataFactory testdataFactory;
|
protected TestdataFactory testdataFactory;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected GridFsOperations operations;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected MongodExecutable mongodExecutable;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ServiceMatcher serviceMatcher;
|
protected ServiceMatcher serviceMatcher;
|
||||||
|
|
||||||
@@ -232,8 +236,8 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void cleanCurrentCollection() {
|
public void cleanCurrentCollection() throws IOException {
|
||||||
operations.delete(new Query());
|
FileUtils.deleteDirectory(new File(artifactFilesystemProperties.getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DefaultMockMvcBuilder createMvcWebAppContext() {
|
protected DefaultMockMvcBuilder createMvcWebAppContext() {
|
||||||
|
|||||||
@@ -180,9 +180,9 @@ public final class RestResourceConversionHelper {
|
|||||||
response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||||
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||||
|
|
||||||
try {
|
try (InputStream inputStream = file.getFileInputStream()) {
|
||||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
copyStreams(inputStream, response.getOutputStream(), controllerManagement, statusId, r.getStart(),
|
||||||
r.getStart(), r.getLength());
|
r.getLength());
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
LOG.error("fullfileRequest of file ({}) failed!", artifact.getFilename(), e);
|
LOG.error("fullfileRequest of file ({}) failed!", artifact.getFilename(), e);
|
||||||
throw new FileSteamingFailedException(artifact.getFilename());
|
throw new FileSteamingFailedException(artifact.getFilename());
|
||||||
@@ -246,8 +246,9 @@ public final class RestResourceConversionHelper {
|
|||||||
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
|
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
|
||||||
response.setStatus(SC_PARTIAL_CONTENT);
|
response.setStatus(SC_PARTIAL_CONTENT);
|
||||||
|
|
||||||
try {
|
|
||||||
for (final ByteRange r : ranges) {
|
for (final ByteRange r : ranges) {
|
||||||
|
try (InputStream inputStream = file.getFileInputStream()) {
|
||||||
|
|
||||||
// Add multipart boundary and header fields for every range.
|
// Add multipart boundary and header fields for every range.
|
||||||
response.getOutputStream().println();
|
response.getOutputStream().println();
|
||||||
response.getOutputStream().println("--" + MULTIPART_BOUNDARY);
|
response.getOutputStream().println("--" + MULTIPART_BOUNDARY);
|
||||||
@@ -255,18 +256,25 @@ public final class RestResourceConversionHelper {
|
|||||||
.println("Content-Range: bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
.println("Content-Range: bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||||
|
|
||||||
// Copy single part range of multi part range.
|
// Copy single part range of multi part range.
|
||||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
copyStreams(inputStream, response.getOutputStream(), controllerManagement, statusId, r.getStart(),
|
||||||
r.getStart(), r.getLength());
|
r.getLength());
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throwFileStreamingFailedException(artifact, e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
// End with final multipart boundary.
|
// End with final multipart boundary.
|
||||||
response.getOutputStream().println();
|
response.getOutputStream().println();
|
||||||
response.getOutputStream().print("--" + MULTIPART_BOUNDARY + "--");
|
response.getOutputStream().print("--" + MULTIPART_BOUNDARY + "--");
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
|
throwFileStreamingFailedException(artifact, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void throwFileStreamingFailedException(final Artifact artifact, final IOException e) {
|
||||||
LOG.error("multipartRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
LOG.error("multipartRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
||||||
throw new FileSteamingFailedException(artifact.getFilename());
|
throw new FileSteamingFailedException(artifact.getFilename());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void handleStandardRangeRequest(final Artifact artifact, final HttpServletResponse response,
|
private static void handleStandardRangeRequest(final Artifact artifact, final HttpServletResponse response,
|
||||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||||
@@ -276,9 +284,9 @@ public final class RestResourceConversionHelper {
|
|||||||
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||||
response.setStatus(SC_PARTIAL_CONTENT);
|
response.setStatus(SC_PARTIAL_CONTENT);
|
||||||
|
|
||||||
try {
|
try (InputStream inputStream = file.getFileInputStream()) {
|
||||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
copyStreams(inputStream, response.getOutputStream(), controllerManagement, statusId, r.getStart(),
|
||||||
r.getStart(), r.getLength());
|
r.getLength());
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
LOG.error("standardRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
LOG.error("standardRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
||||||
throw new FileSteamingFailedException(artifact.getFilename());
|
throw new FileSteamingFailedException(artifact.getFilename());
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.rest;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
|
|
||||||
import org.eclipse.hawkbit.rest.configuration.RestConfiguration;
|
|
||||||
import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
|
||||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract Test for Rest tests.
|
|
||||||
*/
|
|
||||||
@SpringApplicationConfiguration(classes = { RestConfiguration.class,
|
|
||||||
org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
|
|
||||||
public abstract class AbstractRestIntegrationTestWithMongoDB extends AbstractIntegrationTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FilterHttpResponse filterHttpResponse;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DefaultMockMvcBuilder createMvcWebAppContext() {
|
|
||||||
final DefaultMockMvcBuilder createMvcWebAppContext = super.createMvcWebAppContext();
|
|
||||||
return createMvcWebAppContext.addFilter(filterHttpResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -271,11 +271,6 @@
|
|||||||
<artifactId>fest-assert</artifactId>
|
<artifactId>fest-assert</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ru.yandex.qatools.allure</groupId>
|
<groupId>ru.yandex.qatools.allure</groupId>
|
||||||
<artifactId>allure-junit-adaptor</artifactId>
|
<artifactId>allure-junit-adaptor</artifactId>
|
||||||
|
|||||||
7
pom.xml
7
pom.xml
@@ -38,7 +38,7 @@
|
|||||||
<module>hawkbit-security-integration</module>
|
<module>hawkbit-security-integration</module>
|
||||||
<module>hawkbit-http-security</module>
|
<module>hawkbit-http-security</module>
|
||||||
<module>hawkbit-ui</module>
|
<module>hawkbit-ui</module>
|
||||||
<module>hawkbit-artifact-repository-mongo</module>
|
<module>hawkbit-artifact-repository-filesystem</module>
|
||||||
<module>hawkbit-autoconfigure</module>
|
<module>hawkbit-autoconfigure</module>
|
||||||
<module>hawkbit-test-report</module>
|
<module>hawkbit-test-report</module>
|
||||||
<module>examples</module>
|
<module>examples</module>
|
||||||
@@ -670,11 +670,6 @@
|
|||||||
<artifactId>json</artifactId>
|
<artifactId>json</artifactId>
|
||||||
<version>${json.version}</version>
|
<version>${json.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
|
||||||
<version>${embedded-mongo.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.easytesting</groupId>
|
<groupId>org.easytesting</groupId>
|
||||||
<artifactId>fest-assert</artifactId>
|
<artifactId>fest-assert</artifactId>
|
||||||
|
|||||||
Reference in New Issue
Block a user