Workato：Pythonコネクタで /tmp を活用してみる

# はじめに

WorkatoのPythonコネクタでは一時ディレクトリ（/tmp）が利用できないと思っていましたが、検証を進めたところ利用できることがわかりました。

Workatoのコネクタのアクションはそれぞれが独立したコンテナであり、かつエフェメラルなコンテナ（実行後に削除される、揮発性のコンテナ）で実行されるため、アクションを跨いで /tmp の保存内容を共有することはできないのと、実行時間の制限（30秒）に注意する必要はありますが、ちょっとした処理で便利に活用することはできるかと思います。

# 利用例
## 容量の大きなファイルや複数のファイルを処理する

容量の大きなファイルをPythonコネクタのrequestモジュールを利用して直接ダウンロードして取得したり、base64エンコードされたファイルを変数で渡して /tmp へ展開することで、Python3コネクタ上で容量の大きなファイルや複数のファイルを処理することができます。

### 例：URL指定でファイルをダウンロードし/tmpへ保存する

以下の通り Input fieldsおよびOutput fieldsを用意します。Output fieldsは、コードの戻り値に合わせて追加を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/aeb821ab-bec1-28eb-2e90-bf166105ca09.png)

コードは次の通りとします。なお、コード内の記述されている通り、必要な処理や戻り値も設定します。
```python
import requests
import os

def main(input):  
  url = "ダウンロード先のURL"
  output_path = "/tmp/" + input['file_name']
  
  response = requests.get(url)
  with open(output_path, "wb") as file:
    file.write(response.content)

  result = ''
  # ここに必要な処理を記述する

  # 戻り値を設定する（Output fieldsもこれに合わせて変更する）
  # return {"result": result}
```

### 例：base64エンコードされたファイルを変数で渡し、/tmpへ保存する

以下の通り Input fieldsおよびOutput fieldsを用意します。Output fieldsは、コードの戻り値に合わせて追加を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/4160b84e-d443-e8e5-f812-b087e6c75232.png)


コードは次の通りとします。なお、コード内の記述されている通り、必要な処理や戻り値も設定します。
```python
import base64
import os

def main(input):  
  file_data = base64.b64decode(input['file_b64'])
  output_path = "/tmp/" + input['file_name']
  
  with open(output_path, "wb") as file:
    file.write(file_data)

  result = ''
  # ここに必要な処理を記述する

  # 戻り値を設定する（Output fieldsもこれに合わせて変更する）
  # return {"result": result}
```

また、容量のかなり大きなファイルや複数ファイルの場合は、File tools by Workatoコネクタの[Compress files](https://docs.workato.com/features/compress-files.html#input-fields)を利用することで、Workato上でファイルを圧縮してから（gzip圧縮してから）Pythonコネクタへ渡すことが可能です。

https://docs.workato.com/features/compress-files.html#input-fields

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/0f56f1da-2f5c-cc8a-507f-0d6c30cc9a37.png)




## Pythonコネクタに無いコマンドを実行する

responseモジュールを利用し、/tmp にファイルをダウンロードし、実行権限を付与することで、Pythonコネクタに無いコマンドを実行することができます。なお、実行時間の制限（30秒）があることと、ライブラリの制限等、実行上の制限があることから、シングルバイナリ（スタティックバイナリ）として動作するもの（ただしAppImageは不可）、あるいはPythonコネクタで実行可能なスクリプトである必要があります。

### 例：curlをダウンロードして実行する

#### Input fields, Output fields
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/21e9160c-6503-e734-de8b-3c11d70d342b.png)


#### Code
```python
import requests
import subprocess
import os

def main(input):  
  url = "https://github.com/moparisthebest/static-curl/releases/download/v8.7.1/curl-amd64"
  output_path = "/tmp/curl"
  
  response = requests.get(url)
  with open(output_path, "wb") as file:
    file.write(response.content)
    
  os.chmod(output_path, 0o755)
  
  process = subprocess.Popen(input['shell_script'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  stdout, stderr = process.communicate()
  
  return {"stdout": stdout.decode(), "stderr": stderr.decode()}
  ```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/beb6c2e5-ec3b-154d-42a2-9fced3a68b98.png)

#### 注意事項

上記コードでは都度ファイルを取得していますが、ダウンロード先がアプリケーション（コマンド）の配布先URLである場合は、配布先のサーバに過度な負荷を与えないよう、予めダウンロードしておいたファイルを利用することを推奨します。