|
| 1 | +""" |
| 2 | +場所: tools/s3_create_bucket.py |
| 3 | +内容: 指定された名前とリージョンで S3 バケットを作成し、結果を返すツール。 |
| 4 | +目的: ワークフロー内からバケットを安全に新規作成し、後続処理での利用を容易にする。 |
| 5 | +""" |
| 6 | + |
| 7 | +from __future__ import annotations |
| 8 | + |
| 9 | +from collections.abc import Generator |
| 10 | +from typing import Any |
| 11 | + |
| 12 | +import boto3 |
| 13 | +from botocore.exceptions import ClientError |
| 14 | + |
| 15 | +from dify_plugin import Tool |
| 16 | +from dify_plugin.entities.tool import ToolInvokeMessage |
| 17 | + |
| 18 | +try: # pragma: no cover - import path differs when packaged |
| 19 | + from my_aws_tools.provider.utils import ( |
| 20 | + build_boto3_client_kwargs, |
| 21 | + resolve_aws_credentials, |
| 22 | + reset_clients_on_credential_change, |
| 23 | + ) |
| 24 | +except ModuleNotFoundError: # pragma: no cover |
| 25 | + from provider.utils import ( |
| 26 | + build_boto3_client_kwargs, |
| 27 | + resolve_aws_credentials, |
| 28 | + reset_clients_on_credential_change, |
| 29 | + ) |
| 30 | + |
| 31 | + |
| 32 | +class S3CreateBucket(Tool): |
| 33 | + s3_client: Any = None |
| 34 | + |
| 35 | + def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]: |
| 36 | + """S3 バケットを作成し、作成結果のサマリを返す。""" |
| 37 | + |
| 38 | + try: |
| 39 | + credentials = resolve_aws_credentials(self, tool_parameters) |
| 40 | + if tool_parameters.get("aws_region"): |
| 41 | + credentials["aws_region"] = tool_parameters["aws_region"] |
| 42 | + |
| 43 | + reset_clients_on_credential_change(self, credentials, ["s3_client"]) |
| 44 | + if not self.s3_client: |
| 45 | + client_kwargs = build_boto3_client_kwargs(credentials) |
| 46 | + self.s3_client = boto3.client("s3", **client_kwargs) |
| 47 | + except Exception as exc: # pragma: no cover - boto3 init errors |
| 48 | + yield self.create_text_message(f"Failed to initialize AWS client: {exc}") |
| 49 | + return |
| 50 | + |
| 51 | + bucket_name = (tool_parameters.get("bucket_name") or "").strip() |
| 52 | + if not bucket_name: |
| 53 | + yield self.create_text_message("bucket_name parameter is required") |
| 54 | + return |
| 55 | + |
| 56 | + region = credentials.get("aws_region") or "us-east-1" |
| 57 | + acl = (tool_parameters.get("acl") or "").strip() |
| 58 | + |
| 59 | + create_kwargs: dict[str, Any] = {"Bucket": bucket_name} |
| 60 | + if acl: |
| 61 | + create_kwargs["ACL"] = acl |
| 62 | + |
| 63 | + if region != "us-east-1": |
| 64 | + create_kwargs["CreateBucketConfiguration"] = {"LocationConstraint": region} |
| 65 | + |
| 66 | + try: |
| 67 | + response = self.s3_client.create_bucket(**create_kwargs) |
| 68 | + except ClientError as exc: |
| 69 | + error_message = exc.response.get("Error", {}).get("Message", str(exc)) |
| 70 | + yield self.create_text_message(f"Failed to create bucket: {error_message}") |
| 71 | + return |
| 72 | + except Exception as exc: # pragma: no cover - unexpected errors |
| 73 | + yield self.create_text_message(f"Failed to create bucket: {exc}") |
| 74 | + return |
| 75 | + |
| 76 | + location = response.get("Location") |
| 77 | + payload = { |
| 78 | + "bucket_name": bucket_name, |
| 79 | + "region": region, |
| 80 | + "acl": acl or "private", |
| 81 | + "location": location or f"/{bucket_name}", |
| 82 | + "s3_uri": f"s3://{bucket_name}/", |
| 83 | + } |
| 84 | + |
| 85 | + yield self.create_json_message(payload) |
| 86 | + yield self.create_text_message( |
| 87 | + f"Bucket '{bucket_name}' created in {region}. Location: {payload['location']}" |
| 88 | + ) |
0 commit comments