From 2efbf02b06979a56d464b7bec465a13812cfb879 Mon Sep 17 00:00:00 2001 From: Maciej Swiderski Date: Tue, 2 Jan 2024 13:27:45 +0100 Subject: [PATCH] added support for azure blob store as file storage --- .../automatiko-files-azure-blob-addon/pom.xml | 65 ++++++ .../addon/files/s3/AzureBlobStoreFile.java | 67 +++++++ .../AzureBlobStoreFileVariableAugmentor.java | 189 ++++++++++++++++++ .../addon/files/s3/AzureBlobStoreStore.java | 113 +++++++++++ .../files/s3/CleanFilesEventListener.java | 47 +++++ .../files/s3/web/FileDownloadResource.java | 73 +++++++ .../resources/META-INF/io.automatiko.addon | 1 + addons/files/pom.xml | 3 +- .../engine/api/config/AzureFilesConfig.java | 13 ++ .../engine/api/config/FilesConfig.java | 5 + bom/pom.xml | 11 + integration-tests/automatiko-files/pom.xml | 10 +- .../src/main/resources/application.properties | 4 + pom.xml | 3 +- quarkus-extension/bom/pom.xml | 7 + .../quarkus/AzureFilesRuntimeConfig.java | 23 +++ .../engine/quarkus/FilesRuntimeConfig.java | 11 + 17 files changed, 642 insertions(+), 3 deletions(-) create mode 100644 addons/files/automatiko-files-azure-blob-addon/pom.xml create mode 100644 addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFile.java create mode 100644 addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFileVariableAugmentor.java create mode 100644 addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreStore.java create mode 100644 addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/CleanFilesEventListener.java create mode 100644 addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/web/FileDownloadResource.java create mode 100644 addons/files/automatiko-files-azure-blob-addon/src/main/resources/META-INF/io.automatiko.addon create mode 100644 api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/AzureFilesConfig.java create mode 100644 quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/AzureFilesRuntimeConfig.java diff --git a/addons/files/automatiko-files-azure-blob-addon/pom.xml b/addons/files/automatiko-files-azure-blob-addon/pom.xml new file mode 100644 index 000000000..bed8776ec --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/pom.xml @@ -0,0 +1,65 @@ + + 4.0.0 + + io.automatiko + files + 0.0.0-SNAPSHOT + + + io.automatiko.addons + automatiko-files-azure-blob-addon + Automatiko Engine :: Add-Ons :: Files :: Azure BlobStore + Files based on Azure BlobStore AddOn for Automatiko Engine + + + io.automatiko.addons.files.azureblob + + + + + io.automatiko.engine + automatiko-engine-api + + + io.automatiko.workflow + automatiko-workflow-core + + + io.quarkus + quarkus-resteasy-reactive + + + org.eclipse.microprofile.openapi + microprofile-openapi-api + provided + + + com.fasterxml.jackson.core + jackson-annotations + + + + io.quarkiverse.azureservices + quarkus-azure-storage-blob + 1.0.1 + + + + + + io.smallrye + jandex-maven-plugin + + + make-index + + jandex + + + + + + + diff --git a/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFile.java b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFile.java new file mode 100644 index 000000000..b96524409 --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFile.java @@ -0,0 +1,67 @@ +package io.automatiko.addon.files.s3; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; + +import io.automatiko.engine.workflow.file.ByteArrayFile; +import io.quarkus.arc.Arc; + +@JsonAutoDetect(fieldVisibility = Visibility.PUBLIC_ONLY) +public class AzureBlobStoreFile extends ByteArrayFile { + + private String url; + + public AzureBlobStoreFile(String name, byte[] content) { + super(name, content); + } + + @JsonCreator + public AzureBlobStoreFile(@JsonProperty("name") String name, @JsonProperty("content") byte[] content, + @JsonProperty("attributes") Map attributes) { + super(name, content, attributes); + } + + @JsonGetter + public String name() { + return name; + } + + public byte[] content() { + if (content == null) { + AzureBlobStoreStore store = Arc.container().instance(AzureBlobStoreStore.class).orElse(null); + if (store != null) { + content = store.content(url()); + } + } + + return content; + } + + @Override + @JsonGetter + public Map attributes() { + return attributes; + } + + @Override + @JsonGetter + public String url() { + return url; + } + + @JsonSetter + public void url(String url) { + this.url = url; + } + + @Override + public String toString() { + return "AzureBlob [name=" + name + ", content (url)=" + url + ", attributes=" + attributes + "]"; + } +} diff --git a/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFileVariableAugmentor.java b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFileVariableAugmentor.java new file mode 100644 index 000000000..cc9533834 --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreFileVariableAugmentor.java @@ -0,0 +1,189 @@ +package io.automatiko.addon.files.s3; + +import java.util.ArrayList; +import java.util.Collection; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import io.automatiko.engine.api.workflow.Variable; +import io.automatiko.engine.api.workflow.VariableAugmentor; +import io.automatiko.engine.api.workflow.files.HasFiles; +import io.automatiko.engine.workflow.file.ByteArrayFile; + +@ApplicationScoped +public class AzureBlobStoreFileVariableAugmentor implements VariableAugmentor { + + private String serviceUrl; + + private AzureBlobStoreStore store; + + @Inject + public AzureBlobStoreFileVariableAugmentor(AzureBlobStoreStore store) { + this.store = store; + this.serviceUrl = store.urlPrefix(); + } + + @Override + public boolean accept(Variable variable, Object value) { + if (value == null) { + // check variable definition + if (variable.getType().getClassType() != null) { + return ByteArrayFile.class.isAssignableFrom(variable.getType().getClassType()); + } + return false; + } + + if (value instanceof HasFiles) { + value = ((HasFiles) value).files(); + } + + if (value instanceof ByteArrayFile) { + return true; + } + + if (value instanceof Collection) { + return ((Collection) value).stream().anyMatch(item -> item instanceof ByteArrayFile); + } + return false; + } + + @Override + public Object augmentOnCreate(String processId, String processVersion, String processInstanceId, Variable variable, + Object value) { + Object originalValue = value; + value = retrieveValue(value); + if (value == null) { + return value; + } + StringBuilder url = new StringBuilder(serviceUrl); + url.append(processId).append("/"); + if (processVersion != null && !processVersion.isEmpty()) { + url.append(processVersion).append("/"); + } + url.append(processInstanceId).append("/").append(variable.getName()); + + if (value instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) value; + if (file.content() != null) { + AzureBlobStoreFile fsFile = new AzureBlobStoreFile(file.name(), null, file.attributes()); + fsFile.url(url.toString() + "/" + file.name()); + + // store file on file system + store.save(file, processId, processVersion, processInstanceId, variable.getName(), + file.name()); + value = updateValue(originalValue, fsFile); + } + } else if (value instanceof Collection) { + Collection fsFiles = new ArrayList<>(); + for (Object potentialFile : (Collection) value) { + if (potentialFile instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) potentialFile; + if (file.content() != null) { + AzureBlobStoreFile fsFile = new AzureBlobStoreFile(file.name(), null, file.attributes()); + fsFile.url(url.toString() + "/" + file.name()); + + // store file on file system + store.save(file, processId, processVersion, processInstanceId, variable.getName(), + file.name()); + fsFiles.add(fsFile); + } else { + fsFiles.add(file); + } + } + } + return updateValue(originalValue, fsFiles); + } + + return value; + } + + @Override + public Object augmentOnUpdate(String processId, String processVersion, String processInstanceId, Variable variable, + Object value) { + Object originalValue = value; + value = retrieveValue(value); + if (value == null) { + return value; + } + StringBuilder url = new StringBuilder(serviceUrl); + url.append(processId).append("/"); + if (processVersion != null && !processVersion.isEmpty()) { + url.append(processVersion).append("/"); + } + url.append(processInstanceId).append("/").append(variable.getName()); + + if (value instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) value; + if (file.content() != null) { + AzureBlobStoreFile fsFile = new AzureBlobStoreFile(file.name(), null, file.attributes()); + fsFile.url(url.toString() + "/" + file.name()); + + // replace file on file system + store.replace(file, processId, processVersion, processInstanceId, variable.getName(), + file.name()); + value = updateValue(originalValue, fsFile); + } + } else if (value instanceof Collection) { + Collection fsFiles = new ArrayList<>(); + for (Object potentialFile : (Collection) value) { + if (potentialFile instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) potentialFile; + if (file.content() != null) { + AzureBlobStoreFile fsFile = new AzureBlobStoreFile(file.name(), null, file.attributes()); + fsFile.url(url.toString() + "/" + file.name()); + + // replace file on file system + store.replace(file, processId, processVersion, processInstanceId, variable.getName(), + file.name()); + fsFiles.add(fsFile); + } else { + fsFiles.add(file); + } + } + } + return updateValue(originalValue, fsFiles); + } + + return value; + } + + @Override + public void augmentOnDelete(String processId, String processVersion, String processInstanceId, Variable variable, + Object value) { + value = retrieveValue(value); + if (value instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) value; + store.remove(processId, processVersion, processInstanceId, variable.getName(), file.name()); + } else if (value instanceof Collection) { + for (Object potentialFile : (Collection) value) { + if (potentialFile instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) potentialFile; + store.remove(processId, processVersion, processInstanceId, variable.getName(), file.name()); + } + } + + } + + } + + protected Object retrieveValue(Object value) { + if (value instanceof HasFiles) { + return ((HasFiles) value).files(); + } + + return value; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected Object updateValue(Object variable, Object value) { + if (variable instanceof HasFiles) { + ((HasFiles) variable).augmentFiles(value); + + return variable; + } + + return value; + } + +} diff --git a/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreStore.java b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreStore.java new file mode 100644 index 000000000..8b628b237 --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/AzureBlobStoreStore.java @@ -0,0 +1,113 @@ +package io.automatiko.addon.files.s3; + +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import com.azure.core.util.BinaryData; +import com.azure.storage.blob.BlobClient; +import com.azure.storage.blob.BlobContainerClient; +import com.azure.storage.blob.BlobServiceClient; + +import io.automatiko.engine.workflow.file.ByteArrayFile; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class AzureBlobStoreStore { + + private String serviceUrl; + + private String bucket; + + private BlobServiceClient client; + + @Inject + public AzureBlobStoreStore(BlobServiceClient client, + @ConfigProperty(name = "quarkus.automatiko.files.azure.bucket") String bucket, + @ConfigProperty(name = "quarkus.automatiko.service-url") Optional serviceUrl) { + this.client = client; + this.serviceUrl = serviceUrl.orElse("http://localhost:8080") + "/management/files/download/"; + this.bucket = bucket; + } + + public String urlPrefix() { + return serviceUrl; + } + + public void save(ByteArrayFile file, String processId, String processVersion, String processInstanceId, + String... name) { + String objectKey = createObjectKey(processId, processVersion, processInstanceId, name); + + BlobContainerClient blobContainerClient = client.createBlobContainerIfNotExists(this.bucket); + BlobClient blobClient = blobContainerClient.getBlobClient(objectKey); + + blobClient.upload(BinaryData.fromBytes(file.content()), true); + } + + public void replace(ByteArrayFile file, String processId, String processVersion, String processInstanceId, + String... name) { + + save(file, processId, processVersion, processInstanceId, name); + } + + public void remove(String processId, String processVersion, String processInstanceId, String... name) { + + String objectKey = createObjectKey(processId, processVersion, processInstanceId, name); + + BlobContainerClient blobContainerClient = client.createBlobContainerIfNotExists(this.bucket); + BlobClient blobClient = blobContainerClient.getBlobClient(objectKey); + blobClient.delete(); + } + + public byte[] content(String url) { + String objectKey = url.replaceFirst(serviceUrl, ""); + + BlobContainerClient blobContainerClient = client.createBlobContainerIfNotExists(bucket); + BlobClient blobClient = blobContainerClient.getBlobClient(objectKey); + + try { + byte[] content = blobClient.downloadContent().toBytes(); + + return content; + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public byte[] content(String processId, String processVersion, String processInstanceId, String... name) + throws FileNotFoundException { + String objectKey = createObjectKey(processId, processVersion, processInstanceId, name); + + BlobContainerClient blobContainerClient = client.createBlobContainerIfNotExists(bucket); + BlobClient blobClient = blobContainerClient.getBlobClient(objectKey); + + try { + byte[] content = blobClient.downloadContent().toBytes(); + + return content; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected String createObjectKey(String processId, String processVersion, String processInstanceId, String... name) { + List elements = new ArrayList<>(); + elements.add(processId); + if (processVersion != null && !processVersion.isEmpty()) { + elements.add(processVersion); + } + elements.add(processInstanceId); + + for (String nameElement : name) { + elements.add(nameElement); + } + + return elements.stream().collect(Collectors.joining("/")); + } +} diff --git a/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/CleanFilesEventListener.java b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/CleanFilesEventListener.java new file mode 100644 index 000000000..21653296d --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/CleanFilesEventListener.java @@ -0,0 +1,47 @@ +package io.automatiko.addon.files.s3; + +import java.util.Collection; +import java.util.Map.Entry; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import io.automatiko.engine.api.event.process.DefaultProcessEventListener; +import io.automatiko.engine.api.event.process.ProcessCompletedEvent; +import io.automatiko.engine.api.runtime.process.ProcessInstance; +import io.automatiko.engine.workflow.file.ByteArrayFile; +import io.quarkus.arc.properties.UnlessBuildProperty; + +@ApplicationScoped +@UnlessBuildProperty(name = "quarkus.automatiko.on-instance-end", stringValue = "keep", enableIfMissing = true) +public class CleanFilesEventListener extends DefaultProcessEventListener { + + private AzureBlobStoreStore store; + + @Inject + public CleanFilesEventListener(AzureBlobStoreStore store) { + this.store = store; + } + + @Override + public void afterProcessCompleted(ProcessCompletedEvent event) { + ProcessInstance pi = event.getProcessInstance(); + + for (Entry variable : pi.getVariables().entrySet()) { + + if (variable.getValue() instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) variable.getValue(); + store.remove(pi.getProcess().getId(), pi.getProcess().getVersion(), pi.getId(), variable.getKey(), file.name()); + } else if (variable.getValue() instanceof Collection) { + for (Object potentialFile : (Collection) variable.getValue()) { + if (potentialFile instanceof ByteArrayFile) { + ByteArrayFile file = (ByteArrayFile) potentialFile; + store.remove(pi.getProcess().getId(), pi.getProcess().getVersion(), pi.getId(), variable.getKey(), + file.name()); + } + } + } + } + } + +} diff --git a/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/web/FileDownloadResource.java b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/web/FileDownloadResource.java new file mode 100644 index 000000000..089d51472 --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/src/main/java/io/automatiko/addon/files/s3/web/FileDownloadResource.java @@ -0,0 +1,73 @@ +package io.automatiko.addon.files.s3.web; + +import java.io.FileNotFoundException; + +import io.automatiko.addon.files.s3.AzureBlobStoreStore; +import io.automatiko.engine.api.workflow.files.File; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.ResponseBuilder; + +@Path("/management/files") +public class FileDownloadResource { + + private AzureBlobStoreStore store; + + @Inject + public FileDownloadResource(AzureBlobStoreStore store) { + this.store = store; + } + + @GET + @Path("download/{processId}/{processInstanceId}/{variable}/{filename}") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response downloadFile(@PathParam("processId") String processId, + @PathParam("processInstanceId") String processInstanceId, + @PathParam("variable") String variable, + @PathParam("filename") String filename) { + try { + byte[] content = store.content(processId, processInstanceId, variable, filename); + + ResponseBuilder response = Response.ok().entity(content); + response.header("Content-Disposition", "attachment;filename=" + filename); + response.header("Content-Type", File.discoverType(filename)); + return response.build(); + } catch (FileNotFoundException e) { + return Response.status(Response.Status.NOT_FOUND.getStatusCode(), "File with name " + filename + " not found") + .build(); + } catch (Exception e) { + + return Response.serverError().build(); + } + } + + @GET + @Path("download/{processId}/{processVersion}/{processInstanceId}/{variable}/{filename}") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response downloadVersionedFile(@PathParam("processId") String processId, + @PathParam("processVersion") String processVersion, + @PathParam("processInstanceId") String processInstanceId, + @PathParam("variable") String variable, + @PathParam("filename") String filename) { + try { + byte[] content = store.content(processId, processVersion, processInstanceId, variable, filename); + + ResponseBuilder response = Response.ok().entity(content); + response.header("Content-Disposition", "attachment;filename=" + filename); + response.header("Content-Type", File.discoverType(filename)); + return response.build(); + } catch (FileNotFoundException e) { + return Response.status(Response.Status.NOT_FOUND.getStatusCode(), "File with name " + filename + " not found") + .build(); + } catch (Exception e) { + + return Response.serverError().build(); + } + } + +} diff --git a/addons/files/automatiko-files-azure-blob-addon/src/main/resources/META-INF/io.automatiko.addon b/addons/files/automatiko-files-azure-blob-addon/src/main/resources/META-INF/io.automatiko.addon new file mode 100644 index 000000000..ef4516480 --- /dev/null +++ b/addons/files/automatiko-files-azure-blob-addon/src/main/resources/META-INF/io.automatiko.addon @@ -0,0 +1 @@ +files-azure \ No newline at end of file diff --git a/addons/files/pom.xml b/addons/files/pom.xml index 4689139ae..8ac5ff63f 100644 --- a/addons/files/pom.xml +++ b/addons/files/pom.xml @@ -15,5 +15,6 @@ automatiko-files-s3-addon automatiko-files-google-storage-addon automatiko-files-mongodb-addon + automatiko-files-azure-blob-addon - \ No newline at end of file + diff --git a/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/AzureFilesConfig.java b/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/AzureFilesConfig.java new file mode 100644 index 000000000..da0d4302f --- /dev/null +++ b/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/AzureFilesConfig.java @@ -0,0 +1,13 @@ +package io.automatiko.engine.api.config; + +import java.util.Optional; + +public class AzureFilesConfig { + + /** + * Determines the bucket/container where files should be stored on Azure BlobStore + */ + public Optional bucket() { + return Optional.empty(); + } +} diff --git a/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/FilesConfig.java b/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/FilesConfig.java index 14e2dda43..2cab28839 100644 --- a/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/FilesConfig.java +++ b/api/automatiko-engine-api/src/main/java/io/automatiko/engine/api/config/FilesConfig.java @@ -21,4 +21,9 @@ public MongodbFilesConfig mongodb() { return new MongodbFilesConfig() { }; } + + public AzureFilesConfig azure() { + return new AzureFilesConfig() { + }; + } } diff --git a/bom/pom.xml b/bom/pom.xml index 2c43d889f..14921b484 100755 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -424,6 +424,17 @@ ${project.version} sources + + io.automatiko.addons + automatiko-files-azure-blob-addon + ${project.version} + + + io.automatiko.addons + automatiko-files-azure-blob-addon + ${project.version} + sources + diff --git a/integration-tests/automatiko-files/pom.xml b/integration-tests/automatiko-files/pom.xml index 7bfffa11b..9783c9e77 100644 --- a/integration-tests/automatiko-files/pom.xml +++ b/integration-tests/automatiko-files/pom.xml @@ -76,7 +76,15 @@ io.automatiko.addons automatiko-files-mongodb-addon - --> + --> + + + io.quarkus diff --git a/integration-tests/automatiko-files/src/main/resources/application.properties b/integration-tests/automatiko-files/src/main/resources/application.properties index cf4071bc9..34c4ebe5b 100644 --- a/integration-tests/automatiko-files/src/main/resources/application.properties +++ b/integration-tests/automatiko-files/src/main/resources/application.properties @@ -31,6 +31,10 @@ quarkus.automatiko.files.fs.location=target/documents #quarkus.google.cloud.project-id=your-project-id #quarkus.google.cloud.service-account-location=/path/service-account-key.json +# Azure BlobStore Storage stored files config +#quarkus.automatiko.files.azure.bucket=automatiko +#quarkus.azure.storage.blob.connection-string=your-connection-string + # allow to pass in user/group query params as authentication info quarkus.automatiko.security.authorized-only=false diff --git a/pom.xml b/pom.xml index 7e6c88403..70dbc08c3 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ 3.0.5 2.5.2 2.0.0 - 3.0.5 + 3.1.2 3.1.0 3.0.1 3.0.1 @@ -121,6 +121,7 @@ 3.5.0 2.0.2 2.5.3 + 1.0.1 3.0.5 3.6.0 diff --git a/quarkus-extension/bom/pom.xml b/quarkus-extension/bom/pom.xml index 6c59af5d1..c86306015 100755 --- a/quarkus-extension/bom/pom.xml +++ b/quarkus-extension/bom/pom.xml @@ -40,6 +40,13 @@ pom import + + io.quarkiverse.azureservices + quarkus-azure-services-bom + ${version.io.quarkiverse.azure-services} + pom + import + diff --git a/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/AzureFilesRuntimeConfig.java b/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/AzureFilesRuntimeConfig.java new file mode 100644 index 000000000..9f9e6413e --- /dev/null +++ b/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/AzureFilesRuntimeConfig.java @@ -0,0 +1,23 @@ +package io.automatiko.engine.quarkus; + +import java.util.Optional; + +import io.automatiko.engine.api.config.AzureFilesConfig; +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; + +@ConfigGroup +public class AzureFilesRuntimeConfig extends AzureFilesConfig { + + /** + * Determines the bucket/container where files should be stored on Azure BlobStore + */ + @ConfigItem + public Optional bucket; + + @Override + public Optional bucket() { + return bucket; + } + +} diff --git a/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/FilesRuntimeConfig.java b/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/FilesRuntimeConfig.java index 0bdde9cad..70ac72501 100644 --- a/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/FilesRuntimeConfig.java +++ b/quarkus-extension/common/src/main/java/io/automatiko/engine/quarkus/FilesRuntimeConfig.java @@ -1,5 +1,6 @@ package io.automatiko.engine.quarkus; +import io.automatiko.engine.api.config.AzureFilesConfig; import io.automatiko.engine.api.config.FileSystemFilesConfig; import io.automatiko.engine.api.config.FilesConfig; import io.automatiko.engine.api.config.GoogleStorageFilesConfig; @@ -35,6 +36,12 @@ public class FilesRuntimeConfig extends FilesConfig { @ConfigItem public MongodbFilesRuntimeConfig mongodb; + /** + * Provides configuration of Azure BlobStore based files + */ + @ConfigItem + public AzureFilesRuntimeConfig azure; + @Override public FileSystemFilesConfig fs() { return fs; @@ -55,4 +62,8 @@ public MongodbFilesConfig mongodb() { return mongodb; } + @Override + public AzureFilesConfig azure() { + return azure; + } }