You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@nifi.apache.org by GitBox <gi...@apache.org> on 2019/03/05 18:25:20 UTC

[GitHub] [nifi] turcsanyip commented on a change in pull request #3339: NIFI-6078: Create PostSlack processor

turcsanyip commented on a change in pull request #3339: NIFI-6078: Create PostSlack processor
URL: https://github.com/apache/nifi/pull/3339#discussion_r262623916
 
 

 ##########
 File path: nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PostSlack.java
 ##########
 @@ -0,0 +1,516 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.nifi.processors.slack;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.util.EntityUtils;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.behavior.WritesAttribute;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.annotation.lifecycle.OnStopped;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.expression.AttributeExpression;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.flowfile.attributes.CoreAttributes;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processor.util.StandardValidators;
+
+import javax.json.Json;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonString;
+import javax.json.stream.JsonParsingException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+@Tags({"slack", "post", "notify"})
+@CapabilityDescription("Sends a message on Slack. The FlowFile content (e.g. an image) can be uploaded and attached to the message.")
+@InputRequirement(InputRequirement.Requirement.INPUT_REQUIRED)
+@DynamicProperty(name = "Arbitrary name", value = "JSON snippet specifying a Slack message \"attachment\"",
+        description = "The property value will be converted to JSON and will be added to the array of attachments in the JSON payload being sent to Slack." +
+                " The property name will not be used by the processor.",
+        expressionLanguageScope = ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+@WritesAttribute(attribute="slack.file.url", description = "The Slack URL of the uploaded file. It will be added if 'Upload FlowFile' has been set to 'Yes'.")
+public class PostSlack extends AbstractProcessor {
+
+    private static final String SLACK_POST_MESSAGE_URL = "https://slack.com/api/chat.postMessage";
+
+    private static final String SLACK_FILE_UPLOAD_URL = "https://slack.com/api/files.upload";
+
+    public static final PropertyDescriptor POST_MESSAGE_URL = new PropertyDescriptor.Builder()
+            .name("post-message-url")
+            .displayName("Post Message URL")
+            .description("Slack Web API URL for posting text messages to channels." +
+                    " It only needs to be changed if Slack changes its API URL.")
+            .required(true)
+            .defaultValue(SLACK_POST_MESSAGE_URL)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .addValidator(StandardValidators.URL_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor FILE_UPLOAD_URL = new PropertyDescriptor.Builder()
+            .name("file-upload-url")
+            .displayName("File Upload URL")
+            .description("Slack Web API URL for uploading files to channels." +
+                    " It only needs to be changed if Slack changes its API URL.")
+            .required(true)
+            .defaultValue(SLACK_FILE_UPLOAD_URL)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .addValidator(StandardValidators.URL_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor ACCESS_TOKEN = new PropertyDescriptor.Builder()
+            .name("access-token")
+            .displayName("Access Token")
+            .description("OAuth Access Token used for authenticating/authorizing the Slack request sent by NiFi.")
+            .required(true)
+            .sensitive(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor CHANNEL = new PropertyDescriptor.Builder()
+            .name("channel")
+            .displayName("Channel")
+            .description("Slack channel, private group, or IM channel to send the message to.")
+            .required(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .build();
+
+    public static final PropertyDescriptor TEXT = new PropertyDescriptor.Builder()
+            .name("text")
+            .displayName("Text")
+            .description("Text of the Slack message to send.")
+            .required(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .build();
+
+    public static final AllowableValue UPLOAD_FLOWFILE_YES = new AllowableValue(
+            "true",
+            "Yes",
+            "Upload and attach FlowFile content to the Slack message."
+    );
+
+    public static final AllowableValue UPLOAD_FLOWFILE_NO = new AllowableValue(
+            "false",
+            "No",
+            "Don't upload and attach FlowFile content to the Slack message."
+    );
+
+    public static final PropertyDescriptor UPLOAD_FLOWFILE = new PropertyDescriptor.Builder()
+            .name("upload-flowfile")
+            .displayName("Upload FlowFile")
+            .description("Whether or not to upload and attach the FlowFile content to the Slack message.")
+            .allowableValues(UPLOAD_FLOWFILE_YES, UPLOAD_FLOWFILE_NO)
+            .required(true)
+            .defaultValue("false")
+            .build();
+
+    public static final PropertyDescriptor FILE_TITLE = new PropertyDescriptor.Builder()
+            .name("file-title")
+            .displayName("File Title")
+            .description("Title of the file displayed in the Slack message." +
+                    " The property value will only be used if 'Upload FlowFile' has been set to 'Yes'.")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .build();
+
+    public static final PropertyDescriptor FILE_NAME = new PropertyDescriptor.Builder()
+            .name("file-name")
+            .displayName("File Name")
+            .description("Name of the file to be uploaded." +
+                    " The property value will only be used if 'Upload FlowFile' has been set to 'Yes'." +
+                    " If the property evaluated to null or empty string, then the file name will be set to 'file' in the Slack message.")
+            .defaultValue("${" + CoreAttributes.FILENAME.key() + "}")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .build();
+
+    public static final PropertyDescriptor FILE_MIME_TYPE = new PropertyDescriptor.Builder()
+            .name("file-mime-type")
+            .displayName("File Mime Type")
+            .description("Mime type of the file to be uploaded." +
+                    " The property value will only be used if 'Upload FlowFile' has been set to 'Yes'." +
+                    " If the property evaluated to null or empty string, then the mime type will be set to 'application/octet-stream' in the Slack message.")
+            .defaultValue("${" + CoreAttributes.MIME_TYPE.key() + "}")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+            .build();
+
+    public static final PropertyDescriptor USERNAME = new PropertyDescriptor
 
 Review comment:
   By default (when the username is not specified) the displayed name in the message is the Slack App name of the bot user who sent the message. I think this should be used always. 
   
   I just added the username property because PutSlack has the same parameter (however, it does not work in PutSlack, because PutSlack uses Slack webhooks and the new version of Slack webhooks does not support the username parameter any more, I guess for the same reason you mentioned).
   
   Just before opening the PR, I was thinking about removing the username/icon properties at all, but in the end I left them in the code to see what the reviewers think about it.
   
   Now I would definitely vote for removing it from the processor properties. What is your opinion?
   
   Another reason is that username parameter works only when you send a text message but not for file upload messages. File uploads always use the Slack app name, because file upload API call does not have the username parameter. This would not be a really consistent behaviour for the end user.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services