How to NOT delete a file in a Azure FTP connector action if the transfer fails in a logic app - azure-logic-apps

I have a successful connection setup between a FTP site and dropbox using a azure logic app. But while setting it up it kept just downloading the file then, since I had the next step wrong, deleting.
In a test environment this is annoying. In production, pretty awful.
Here is the code I am using on the action part:
"operation": "UploadFile",
"parameters": {
"FilePath": "#{triggers().outputs.body.FilePath}",
"content": {
"Content": "#{triggers().outputs.body.Content}",
"ContentTransferEncoding": "None"
},
"overwrite": true
},
Is there anything I can do so that if it fails it leave the file on the server?

I'm not 100% sure what you mean, but I will give it a try. Maybe you can reformulate the question if I misinterpret you.
But yes, there exists "conditions" in Logic Apps which can be used. If you are new to Logic Apps I'd suggest you use "designer view" and you can then click "Add condition to be met". This would visualize a text box in which you can formulate conditions. For instance:
#equals({your data}, bool('true'))
To check if some value is true, or something similar to check if data is null.

Related

Where is a list of browserstack_executor actions?

I've found uses of the following, but no documentation for other possible actions using the browserstack_executor:
fileExists
getFileContent
getFileProperties
setSessionStatus
I'm looking for a removeFile or unlinkFile or deleteFile to remove a file that was downloaded by the browser and is now in the way when the next file downloads and gets a (1) added to the filename.
In my selenium test I'm doing something like this:
if driver._is_remote:
action = {"action": "fileExists", "arguments": {"fileName": os.path.basename(self.filepath)}}
if driver.execute_script(f'browserstack_executor:{json.dumps(action)}'):
action = {"action": "getFileContent", "arguments": {"fileName": os.path.basename(self.filepath)}}
content = driver.execute_script(f'browserstack_executor:{json.dumps(action)}')
with open(self.filepath, "wb") as f:
f.write(base64.b64decode(content))
action = {"action": "deleteFile", "arguments": {"fileName": os.path.basename(self.filepath)}}
delete_status = driver.execute_script(f'browserstack_executor:{json.dumps(action)}')
I keep getting invalid action with all of the 3 I've tried so there must be something else to get rid of a file on the machine at browserstack.
I believe 'browserstack_executor' is a custom executor specific to BrowserStack and has a limited set of operations that it can perform.
The supported operations are available in their documentation:
https://www.browserstack.com/docs/automate/selenium/test-file-upload
https://www.browserstack.com/docs/automate/selenium/test-file-download
Hence, operations like removeFile or unlinkFile or deleteFile, cannot be performed, as they are not supported currently and are also not mentioned in the links shared above.
Per the companies support staff, there is no list and unlink is not supported. In order to work around it I've modified the FileExists ExpectedCondition I was using to auto increment the filename after one is pulled from the test system and to use the "next available" name so that my tests can be the same running locally or on browser stack.

Use parametrized values with Azure Logic App

I'm working with an Azure LogicApp where the workflow have fixed values. Our DevOps tool is VSTS (Visual Studio Team Services) and because we have multiple environments to handle, I have to do some refactoring (using parametrized values) so in VSTS we'll be able to provide environment-specific values.
Thanks to 2 websites I found on Internet I managed to understand that there are 3 kind of parameters :
To understand my problem, here's my action :
I want to have my string "/work/documents" in a parameter value. So in the "Code view" I managed to use a parameter instead of a hard-coded value :
"triggers": {
"When_a_file_is_added_or_modified": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "#parameters('$connections')['sftp_1']['connectionId']"
}
},
"method": "get",
"path": "/datasets/default/triggers/onupdatedfile",
"queries": {
"folderId": "#{parameters('pathToRootFolder')}"
}
},
"recurrence": {
"frequency": "Hour",
"interval": 1
}
}
}
And in my parameters.json :
"sftp_1_path_root_folder": {
"value": "/work/documents"
}
Here's the final result in Visual Studio:
Am I missing something ? Why isn't the value displayed in the Designer ? Thank you for your help in advance !
When you are using Logic Apps parameters inside your Logic App definition, they are not resolved at design-time, but at run-time. Thus, you are not supposed to see them in the designer. If you run the workflow, you should be able to see the actual value at run-time.
If you want to resolve those parameters at deployment-time, then you would need to write directly from the ARM template using ARM parameters into the workflow definition. This is possible, but in some cases, it can become a bit more complex. That's why I prefer to make use of Logic Apps parameters as described here.

Open URL in IBM Watson conversation

I am using a Blumix free account to develop a chat-bot using watson conversation.
How do I add a clickable URL in the response, or automatically call a URL in browser?
I have edited the "advanced response" using the suggestions as described on this page but could not get it work.
How can I achieve that?
I don't know if I understood your question correctly, but.. if you wants add some url inside flows Conversation Service (IBM Watson), try it:
1º: Add the url with tag <a target> and href= your URL inside flows. See the example:
JSON:
"output": {
"text": "This is a link <a target=\"_blank\" href= \"https://www.choosemyplate.gov\">Food and nutrition Guide</a>.\n<br/><br/>Talk to you later, bye for now!"
},
2º See that it did not work inside the Conversation, because it will be your browser that will render the html.
3º If you open with your browser, it works, see:
See that the link is showing up, and this will work for other things in html, like button, for example...
But if you can: based on user input should access a url:
This is done by using two features: Context.request skip_user_input
A request is a special context variable that has args, name and result. It is used to tell the calling app that it should do some action based on this variable.
Setting skip_user_input is optional. In many cases, you might want to execute some business logic in your application and then provide its results via result. Setting skip_user_input to true, will tell Watson Conversation to not wait for input from the user. Thus, your condition on the next node should be based on the content inside result.
{
"output": {},
"context": {
"request": {
"args": {
"url_to_invoke": "your_url"
},
"name": "Call_A_URL",
"result": "context.response"
},
"skip_user_input": true
}
}
Reference: IBM Professional #Dudi: here.

Is including additional information in the output object a good idea?

I'm experimenting with a Conversation where I would like to modify the output in a couple of different ways:
different output for speech or text
different output depending on the tone of the conversation
It looks like I can add extra output details which make it through to the client ok. For example, adding speech alongside text...
{
"output": {
"speech": {
"Hi. Please see my website for details."
},
"link": "http://www.example.com",
"text": {
"Hi. Please see http://www.example.com for details."
}
}
}
For the tone, I wondered about making up a custom selection policy, unfortunately it seems to treat it the same as a random selection policy. For example...
{
"output": {
"text": {
"values": [
"Hello. Please see http://www.example.com for more details.",
"Hi. Please see http://www.example.com for details."
]
},
"append": false,
"selection_policy": "tone"
}
}
I could just add a separate tone-sensitive object to output though so that's not a big problem.
Would there be any issues adding things to output in this way?
You can definitely use the output field to specify custom variables you want your client app to see with the benefit that these variables will not persist across multiple dialog rounds (which they would if you would add them to the context field).
Now currently there is no "easy" way how to define your custom selection policy (apart from the random and sequential supported by the runtime right now) - but you could still return an array of possible answers to the client app with some attribute telling the client app which selection policy to use and you would implement this policy in the client app.

A bug in YouTube's API example on GAE? Or am I missing something?

I'm working with this list videos example for GAE and if you try to run it on that page you can see that there's no next_page_token
I've even tried to self.response.out.write(next_page_token) and got None.
For example purposes I've submitted Channel name to be Google (which surely has more than 50 videos). I only get 50, no token that I can see, no pagination indication or anything like that.
What am I missing here?
Please advise,
Thanks a lot
Here is the first request pre-filled for you. Click execute at the bottom:
https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.channels.list?part=snippet%252CcontentDetails&forUsername=Google&_h=1&
Following that result and hitting the next api in the code,
https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.playlistItems.list?part=snippet&maxResults=50&playlistId=UUK8sQmJBp8GCxrOtXWBpyEA&_h=3&
Clicking execute on that shows that nextPageToken set. Either the code example from Google has a bug in it, or it is a copy paste error somewhere.
EDIT:
There is a bug in the code sample provided.
playlistitems_response looks similar to this:
{
"kind": "youtube#playlistItemListResponse",
"etag": "\"eYE31WLho912TfxEBDDRSwEQ5Ms/vUtg-sAFafmsExy-5XOvaMIfVN0\"",
"nextPageToken": "CDQQAA",
"prevPageToken": "CDIQAQ",
"pageInfo": {
"totalResults": 1634,
"resultsPerPage": 2
},
"items": [{...}]
}
The nextPageToken is being extracted like playlistitems_response.get('tokenPagination', {}).get('nextPageToken') when it
should read playlistitems_response.get('nextPageToken').

Resources