-
Notifications
You must be signed in to change notification settings - Fork 109
Initial commit for WASB MVP #177
base: main
Are you sure you want to change the base?
Changes from all commits
3bfa572
4a3dfb3
8139bdd
0dd1347
f8b3644
18c5fa8
24ca62f
6801bac
3a15e21
7993e4c
8a2592d
af5b03e
628ccce
0a93b17
6dc6eb1
dbf72d6
9ecff35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <artifactId>spring-cloud-stream-azure-storage-parent</artifactId> | ||
| <packaging>pom</packaging> | ||
|
|
||
| <properties> | ||
| <azure.version>4.3.0</azure.version> | ||
| </properties> | ||
|
|
||
| <parent> | ||
| <groupId>org.springframework.cloud.stream.app</groupId> | ||
| <artifactId>spring-cloud-stream-app-starters</artifactId> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shoud use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This conflicts with how the |
||
| <version>1.0.0.BUILD-SNAPSHOT</version> | ||
| </parent> | ||
|
|
||
| <modules> | ||
| <module>spring-cloud-starter-stream-sink-azure-blob</module> | ||
| </modules> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>com.microsoft.azure</groupId> | ||
| <artifactId>azure-storage</artifactId> | ||
| <version>${azure.version}</version> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| </project> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # spring-cloud-stream-wasb-sink | ||
| #### A Windows Azure Storage Blob sink module for Spring Cloud Stream | ||
|
|
||
| This module is an MVP implementation of a BlockBlob-based sink module | ||
| for text payloads originating from a Spring Cloud Dataflow stream. | ||
|
|
||
| An example stream definition: | ||
|
|
||
| ``` | ||
| dataflow:> app register --type sink --name wasb --uri file:///Users/kdunn/.m2/repository/io/pivotal/pde/wasb-sink/0.0.1-SNAPSHOT/wasb-sink-0.0.1-SNAPSHOT.jar | ||
|
|
||
| # CloudBlockBlob (every payload overwrites) | ||
| dataflow:> stream create --name testWasb --definition 'time | wasb --accountName="scdftest" --accountKey="<YOUR STORAGE ACCOUNT KEY HERE>" --containerName="time" --blobName="test" ' --deploy | ||
|
|
||
| # CloudAppendBlob (every payload appends) | ||
| dataflow:> stream create --name testWasb --definition 'time | wasb --accountName="scdftest" --accountKey="<YOUR STORAGE ACCOUNT KEY HERE>" --containerName="time" --blobName="testAppend" --appendOnly=true --overwriteExistingAppend=true ' --deploy | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <artifactId>spring-cloud-starter-stream-sink-wasb</artifactId> | ||
| <name>spring-cloud-starter-stream-sink-wasb</name> | ||
| <description>Spring Cloud Stream Windows Azure Blob Storage Sink</description> | ||
|
|
||
| <parent> | ||
| <groupId>org.springframework.cloud.stream.app</groupId> | ||
| <artifactId>spring-cloud-stream-azure-storage-parent</artifactId> | ||
| <version>1.0.0.BUILD-SNAPSHOT</version> | ||
| </parent> | ||
|
|
||
| <properties> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>org.springframework.cloud.stream.app</groupId> | ||
| <artifactId>app-starters-test-support</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| /* | ||
| * Copyright 2016 the original author or authors. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package org.springframework.cloud.stream.app.azure.storage.sink; | ||
|
|
||
| import java.io.IOException; | ||
| import java.net.URISyntaxException; | ||
| import java.security.InvalidKeyException; | ||
|
|
||
| import org.apache.commons.logging.Log; | ||
| import org.apache.commons.logging.LogFactory; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.boot.SpringApplication; | ||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| import org.springframework.cloud.stream.annotation.EnableBinding; | ||
| import org.springframework.cloud.stream.messaging.Sink; | ||
| import org.springframework.context.annotation.DependsOn; | ||
| import org.springframework.integration.annotation.ServiceActivator; | ||
| import org.springframework.messaging.Message; | ||
| import org.springframework.messaging.MessagingException; | ||
|
|
||
| // Include the following imports to use blob APIs. | ||
| import com.microsoft.azure.storage.CloudStorageAccount; | ||
| import com.microsoft.azure.storage.StorageException; | ||
| import com.microsoft.azure.storage.blob.BlobContainerPermissions; | ||
| import com.microsoft.azure.storage.blob.BlobContainerPublicAccessType; | ||
| import com.microsoft.azure.storage.blob.CloudBlob; | ||
| import com.microsoft.azure.storage.blob.CloudAppendBlob; | ||
| import com.microsoft.azure.storage.blob.CloudBlobClient; | ||
| import com.microsoft.azure.storage.blob.CloudBlobContainer; | ||
| import com.microsoft.azure.storage.blob.CloudBlockBlob; | ||
|
|
||
|
|
||
| /** | ||
| * @author Kyle Dunn | ||
| */ | ||
| @EnableBinding(Sink.class) | ||
| @EnableConfigurationProperties(AzureBlobSinkProperties.class) | ||
| @SpringBootApplication | ||
| public class AzureBlobSinkConfiguration { | ||
|
|
||
| @Autowired | ||
| private AzureBlobSinkProperties properties; | ||
|
|
||
| private static Log logger = LogFactory.getLog(AzureBlobSinkConfiguration.class); | ||
|
|
||
| private CloudBlob blobService; | ||
|
|
||
| @Autowired | ||
| public void setBlobService() throws StorageException, URISyntaxException, InvalidKeyException { | ||
| // Define the connection-string with your values | ||
| final String storageConnectionString = | ||
| "DefaultEndpointsProtocol=" + this.properties.getDefaultEndpointsProtocol() + | ||
| ";AccountName=" + this.properties.getAccountName() + | ||
| ";AccountKey=" + this.properties.getAccountKey(); | ||
|
|
||
| // Setup the cloud storage account. | ||
| CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString); | ||
|
|
||
| logger.info("getBlobService() : using account " + this.properties.getAccountName()); | ||
|
|
||
| // Create a blob service client | ||
| CloudBlobClient blobClient = account.createCloudBlobClient(); | ||
|
|
||
| // Get a reference to a container | ||
| // The container name must be lower case | ||
| CloudBlobContainer container = blobClient.getContainerReference(this.properties.getContainerName().toLowerCase()); | ||
|
|
||
| logger.info("getBlobService() : using container " + this.properties.getContainerName()); | ||
|
|
||
| if (this.properties.getAutoCreateContainer()) { | ||
| container.createIfNotExists(); | ||
| } | ||
|
|
||
| // Make the container public | ||
| if (this.properties.getPublicPermission()) { | ||
| logger.info("getBlobService() : making container publicly accessible"); | ||
|
|
||
| // Create a permissions object | ||
| BlobContainerPermissions containerPermissions = new BlobContainerPermissions(); | ||
|
|
||
| // Include public access in the permissions object | ||
| containerPermissions.setPublicAccess(BlobContainerPublicAccessType.CONTAINER); | ||
|
|
||
| // Set the permissions on the container | ||
| container.uploadPermissions(containerPermissions); | ||
| } | ||
|
|
||
| logger.info("getBlobService() : using blob name " + this.properties.getBlobName()); | ||
|
|
||
| if (this.properties.getAppendOnly()) { | ||
| this.blobService = container.getAppendBlobReference(this.properties.getBlobName()); | ||
| if (this.properties.getOverwiteExistingAppend()) { | ||
| ((CloudAppendBlob) blobService).createOrReplace(); | ||
| } | ||
| } | ||
| else { | ||
| this.blobService = container.getBlockBlobReference(this.properties.getBlobName()); | ||
| } | ||
| } | ||
|
|
||
| @ServiceActivator(inputChannel=Sink.INPUT) | ||
| public void pushToAzureBlob(Message<?> message) throws StorageException, IOException { | ||
| // Upload the payload to the blob | ||
| if (this.properties.getAppendOnly()) { | ||
| ((CloudAppendBlob) blobService).appendText(message.getPayload().toString()); | ||
| } | ||
| else { | ||
| ((CloudBlockBlob) blobService).uploadText(message.getPayload().toString()); | ||
| } | ||
| } | ||
|
|
||
| public static void main(String[] args) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this stuff. Would be better to write your own |
||
| SpringApplication.run(AzureBlobSinkConfiguration.class, args); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| /* | ||
| * Copyright 2016 the original author or authors. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.springframework.cloud.stream.app.azure.storage.sink; | ||
|
|
||
| import static org.springframework.integration.handler.LoggingHandler.Level.*; | ||
|
|
||
| import javax.validation.constraints.NotNull; | ||
|
|
||
| import org.hibernate.validator.constraints.NotBlank; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| import org.springframework.integration.handler.LoggingHandler; | ||
|
|
||
| /** | ||
| * Configuration properties for the Azure Blob Sink module. | ||
| * | ||
| * @author Kyle Dunn | ||
| */ | ||
| @ConfigurationProperties("azure.blob") | ||
| public class AzureBlobSinkProperties { | ||
|
|
||
| /** | ||
| * The default Azure endpoint protocol. | ||
| */ | ||
| private String defaultEndpointsProtocol = "http"; | ||
|
|
||
| /** | ||
| * The Azure Storage Account name. | ||
| */ | ||
| private String account; | ||
|
|
||
| /** | ||
| * The Azure Storage Account key. | ||
| */ | ||
| private String key; | ||
|
|
||
| /** | ||
| * The Azure Storage Container name. | ||
| */ | ||
| private String container; | ||
|
|
||
| /** | ||
| * The Azure Storage Blob name. | ||
| */ | ||
| private String blob; | ||
|
|
||
| /** | ||
| * Create a container if it doesn't already exist. | ||
| */ | ||
| private boolean createContainer = true; | ||
|
|
||
| /** | ||
| * Set container access policy to public. | ||
| */ | ||
| private boolean publicPermission = true; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some JavaDocs mix up has happened for these two properties
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like it would be better to rely on the I'd avoid extra service call, even if it is: |
||
|
|
||
| /** | ||
| * Specify if using an CloudAppendBlob | ||
| */ | ||
| private boolean appendOnly = true; | ||
|
|
||
| /** | ||
| * Specify whether to silently overwrite | ||
| * existing an CloudAppendBlob with the same name | ||
| */ | ||
| private boolean overwriteExistingAppend = false; | ||
|
|
||
| public String getDefaultEndpointsProtocol() { | ||
| return defaultEndpointsProtocol; | ||
| } | ||
|
|
||
| public void setDefaultEndpointsProtocol(String p) { | ||
| this.defaultEndpointsProtocol = p; | ||
| } | ||
|
|
||
| public String getAccountName() { | ||
| return account; | ||
| } | ||
|
|
||
| public void setAccountName(String n) { | ||
| this.account = n; | ||
| } | ||
|
|
||
| public String getAccountKey() { | ||
| return key; | ||
| } | ||
|
|
||
| public void setAccountKey(String k) { | ||
| this.key = k; | ||
| } | ||
|
|
||
| public String getContainerName() { | ||
| return container; | ||
| } | ||
|
|
||
| public void setContainerName(String c) { | ||
| this.container = c; | ||
| } | ||
|
|
||
| public String getBlobName() { | ||
| return blob; | ||
| } | ||
|
|
||
| public void setBlobName(String b) { | ||
| this.blob = b; | ||
| } | ||
|
|
||
| public boolean getAutoCreateContainer() { | ||
| return createContainer; | ||
| } | ||
|
|
||
| // Automatically create the container | ||
| public void setAutoCreateContainer(Boolean b) { | ||
| this.createContainer = b; | ||
| } | ||
|
|
||
| public boolean getPublicPermission() { | ||
| return publicPermission; | ||
| } | ||
|
|
||
| // Include public access in the permissions object | ||
| public void setPublicPermission(Boolean b) { | ||
| this.publicPermission = b; | ||
| } | ||
|
|
||
| public boolean getAppendOnly() { | ||
| return appendOnly; | ||
| } | ||
|
|
||
| public void setAppendOnly(Boolean appendOnly) { | ||
| this.appendOnly = appendOnly; | ||
| } | ||
|
|
||
| public boolean getOverwiteExistingAppend() { | ||
| return overwriteExistingAppend; | ||
| } | ||
|
|
||
| public void setOverwriteExistingAppend(Boolean overwrite) { | ||
| this.overwriteExistingAppend = overwrite; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
azure-storagemodule must to be included in the root pom. Otherwise it isn't imported into IDE automatically.And I guess won't be visible for building via Maven.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in latest commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you are doing locally, but this change isn't present in the current PR state.
You should do changes, perform commit and push to
origin.The PR here in GH picks up all the changes automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if you were suggesting the dependency be moved to the parent or something else. The former is what is reflected below.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Looks like we don't understand each other a bit.
Sorry for my bad English or for anything else I'm saying is unclear.
I mean that we should add
<module>azure-storage</module>into<modules>of root pom of the entire project.I could make the polishing for you do demonstrate what I have in mind on the matter, but I can't do that against your
master. Having my infrastructure polishing you can integrate that commit into your branch and go ahead with other Blob Storage stuff to reach some finish.But that would be enough complex if you you are still on
master.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the first part. This should have been obvious to me - thank you for clarifying? :-)