ruby_llm-docker 0.0.1 โ†’ 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Test script for RubyLLM Docker Tools
5
+ # This verifies that all Docker tools load correctly and the chat system works
6
+ # without requiring an OpenAI API key or active Docker daemon
7
+
8
+ require_relative '../lib/ruby_llm/docker'
9
+
10
+ puts '๐Ÿงช Testing Docker Chat functionality...'
11
+
12
+ # Test 1: Check that all tools are available
13
+ puts "\n1. Testing tool loading:"
14
+ tools = RubyLLM::Docker.all_tools
15
+ puts "โœ… Found #{tools.size} Docker tools"
16
+ expected_tools = 22
17
+ if tools.size == expected_tools
18
+ puts "โœ… Expected number of tools loaded (#{expected_tools})"
19
+ else
20
+ puts "โŒ Expected #{expected_tools} tools, but found #{tools.size}"
21
+ exit 1
22
+ end
23
+
24
+ # Test 2: Check that all tools are valid RubyLLM::Tool classes
25
+ puts "\n2. Testing tool validity:"
26
+ invalid_tools = tools.reject { |tool| tool < RubyLLM::Tool }
27
+ if invalid_tools.empty?
28
+ puts 'โœ… All tools inherit from RubyLLM::Tool'
29
+ else
30
+ puts "โŒ Invalid tools found: #{invalid_tools.map(&:name)}"
31
+ exit 1
32
+ end
33
+
34
+ # Test 3: Test helper method (without actually creating a chat)
35
+ puts "\n3. Testing helper methods:"
36
+ begin
37
+ # Create a mock chat object to test the method exists
38
+ mock_chat = Object.new
39
+ def mock_chat.with_tool(_tool_class)
40
+ self
41
+ end
42
+
43
+ result = RubyLLM::Docker.add_all_tools_to_chat(mock_chat)
44
+ if result == mock_chat
45
+ puts 'โœ… add_all_tools_to_chat method works correctly'
46
+ else
47
+ puts 'โŒ add_all_tools_to_chat method failed'
48
+ exit 1
49
+ end
50
+ rescue StandardError => e
51
+ puts "โŒ Helper method test failed: #{e.message}"
52
+ exit 1
53
+ end
54
+
55
+ # Test 4: Check that docker_chat.rb file exists and is executable
56
+ puts "\n4. Testing chat script availability:"
57
+ chat_script = File.join(__dir__, 'docker_chat.rb')
58
+ if File.exist?(chat_script)
59
+ puts 'โœ… docker_chat.rb exists'
60
+
61
+ if File.executable?(chat_script)
62
+ puts 'โœ… docker_chat.rb is executable'
63
+ else
64
+ puts 'โš ๏ธ docker_chat.rb is not executable (run: chmod +x examples/docker_chat.rb)'
65
+ end
66
+ else
67
+ puts 'โŒ docker_chat.rb not found'
68
+ exit 1
69
+ end
70
+
71
+ puts "\n๐ŸŽ‰ All tests passed!"
72
+ puts "\n๐Ÿ“ Next steps:"
73
+ puts " 1. Set your OpenAI API key: export OPENAI_API_KEY='your-key-here'"
74
+ puts ' 2. Run the chat: ruby examples/docker_chat.rb'
75
+ puts ' 3. Or run with: ./examples/docker_chat.rb'
76
+ puts "\n๐Ÿ’ก Example chat commands to try:"
77
+ puts " โ€ข 'How many containers are running?'"
78
+ puts " โ€ข 'Show me all Docker images'"
79
+ puts " โ€ข 'List Docker networks'"
80
+ puts " โ€ข '/help' - to see all available tools"
81
+ puts " โ€ข '/exit' - to quit the chat"
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for building Docker images.
6
+ #
7
+ # This tool provides the ability to build Docker images from Dockerfile
8
+ # content. It creates custom images by executing Dockerfile instructions
9
+ # and supports comprehensive build configuration including tagging and
10
+ # build arguments.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Build images from Dockerfile content strings
15
+ # - Support for custom image tagging
16
+ # - Comprehensive build output and error reporting
17
+ # - Handles all standard Dockerfile instructions
18
+ # - Build context management
19
+ # - Progress tracking and logging
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # Image building involves significant security risks:
24
+ # - **Code Execution**: Dockerfile RUN commands execute arbitrary code
25
+ # - **Network Access**: Build process can access networks and repositories
26
+ # - **File System Access**: Can read local files and directories
27
+ # - **Credential Exposure**: May expose build-time secrets and credentials
28
+ # - **Supply Chain Risk**: Downloaded packages may contain malware
29
+ # - **Resource Consumption**: Builds can consume significant CPU, memory, and storage
30
+ #
31
+ # **Security Recommendations**:
32
+ # - Review all Dockerfile content before building
33
+ # - Use trusted base images only
34
+ # - Avoid embedding secrets in image layers
35
+ # - Implement build isolation and sandboxing
36
+ # - Monitor build resource consumption
37
+ # - Scan built images for vulnerabilities
38
+ # - Use multi-stage builds to minimize attack surface
39
+ #
40
+ # == Parameters
41
+ #
42
+ # - **dockerfile**: Dockerfile content as a string (required)
43
+ # - **tag**: Tag for the built image (optional, e.g., "myimage:latest")
44
+ #
45
+ # == Example Usage
46
+ #
47
+ # # Build simple image
48
+ # dockerfile_content = <<~DOCKERFILE
49
+ # FROM alpine:latest
50
+ # RUN apk add --no-cache curl
51
+ # CMD ["curl", "--version"]
52
+ # DOCKERFILE
53
+ #
54
+ # response = BuildImage.call(
55
+ # server_context: context,
56
+ # dockerfile: dockerfile_content,
57
+ # tag: "my-curl:latest"
58
+ # )
59
+ #
60
+ # # Build web server image
61
+ # dockerfile_content = <<~DOCKERFILE
62
+ # FROM nginx:alpine
63
+ # COPY nginx.conf /etc/nginx/nginx.conf
64
+ # EXPOSE 80
65
+ # CMD ["nginx", "-g", "daemon off;"]
66
+ # DOCKERFILE
67
+ #
68
+ # response = BuildImage.call(
69
+ # server_context: context,
70
+ # dockerfile: dockerfile_content,
71
+ # tag: "custom-nginx:v1.0"
72
+ # )
73
+ #
74
+ # @see ::Docker::Image.build_from_dir
75
+ # @since 0.1.0
76
+ BUILD_IMAGE_DEFINITION = ToolForge.define(:build_image) do
77
+ description 'Build a Docker image'
78
+
79
+ param :dockerfile,
80
+ type: :string,
81
+ description: 'Dockerfile content as a string'
82
+
83
+ param :tag,
84
+ type: :string,
85
+ description: 'Tag for the built image (e.g., "myimage:latest")',
86
+ required: false
87
+
88
+ execute do |dockerfile:, tag: nil|
89
+ # Build the image
90
+ image = ::Docker::Image.build(dockerfile)
91
+
92
+ # If a tag was specified, tag the image
93
+ if tag
94
+ # Split tag into repo and tag parts
95
+ repo, image_tag = tag.split(':', 2)
96
+ image_tag ||= 'latest'
97
+ image.tag('repo' => repo, 'tag' => image_tag, 'force' => true)
98
+ end
99
+
100
+ response_text = "Image built successfully. ID: #{image.id}"
101
+ response_text += ", Tag: #{tag}" if tag
102
+ response_text
103
+ rescue StandardError => e
104
+ "Error building image: #{e.message}"
105
+ end
106
+ end
107
+
108
+ BuildImage = BUILD_IMAGE_DEFINITION.to_ruby_llm_tool
109
+ end
110
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for copying files and directories to Docker containers.
6
+ #
7
+ # This tool provides the ability to copy files and directories from the
8
+ # local host filesystem into running Docker containers. It supports both
9
+ # individual files and entire directory trees, with optional ownership
10
+ # modification within the container.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Copy files and directories from host to container
15
+ # - Supports recursive directory copying
16
+ # - Preserves file permissions and metadata
17
+ # - Optional ownership modification after copy
18
+ # - Works with running containers
19
+ # - Comprehensive error handling and validation
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # File copying operations have significant security implications:
24
+ # - **File System Access**: Reads local host file system content
25
+ # - **Container Modification**: Alters container file system state
26
+ # - **Data Injection**: Can introduce malicious files into containers
27
+ # - **Permission Escalation**: May affect container security context
28
+ # - **Resource Consumption**: Large copies can consume storage and I/O
29
+ # - **Path Traversal**: Improper paths could access unintended locations
30
+ #
31
+ # **Security Recommendations**:
32
+ # - Validate and sanitize all file paths
33
+ # - Implement access controls for source file locations
34
+ # - Monitor file copy operations and sizes
35
+ # - Use read-only mounts where possible
36
+ # - Apply resource limits to prevent abuse
37
+ #
38
+ # == Parameters
39
+ #
40
+ # - **id**: Container ID or name (required)
41
+ # - **source_path**: Path to file/directory on local filesystem (required)
42
+ # - **destination_path**: Path inside container for copied content (required)
43
+ # - **owner**: Owner for copied files (optional, e.g., "1000:1000" or "username:group")
44
+ #
45
+ # == Example Usage
46
+ #
47
+ # # Copy single file
48
+ # response = CopyToContainer.call(
49
+ # server_context: context,
50
+ # id: "web-server",
51
+ # source_path: "/local/config.conf",
52
+ # destination_path: "/etc/nginx/nginx.conf"
53
+ # )
54
+ #
55
+ # # Copy directory with ownership change
56
+ # response = CopyToContainer.call(
57
+ # server_context: context,
58
+ # id: "app-container",
59
+ # source_path: "/local/app-data",
60
+ # destination_path: "/var/lib/app",
61
+ # owner: "app:app"
62
+ # )
63
+ #
64
+ # @see ::Docker::Container#archive_in_stream
65
+ # @since 0.1.0
66
+ COPY_TO_CONTAINER_DEFINITION = ToolForge.define(:copy_to_container) do
67
+ description 'Copy a file or directory from the local filesystem into a running Docker container. ' \
68
+ 'The source path is on the local machine, and the destination path is inside the container.'
69
+
70
+ param :id,
71
+ type: :string,
72
+ description: 'Container ID or name'
73
+
74
+ param :source_path,
75
+ type: :string,
76
+ description: 'Path to the file or directory on the local filesystem to copy'
77
+
78
+ param :destination_path,
79
+ type: :string,
80
+ description: 'Path inside the container where the file/directory should be copied'
81
+
82
+ param :owner,
83
+ type: :string,
84
+ description: 'Owner for the copied files (optional, e.g., "1000:1000" or "username:group")',
85
+ required: false
86
+
87
+ # Helper method for adding files/directories to tar
88
+ class_helper :add_to_tar do |tar, path, archive_path|
89
+ if File.directory?(path)
90
+ # Add directory entry
91
+ tar.mkdir(archive_path, File.stat(path).mode)
92
+
93
+ # Add directory contents
94
+ Dir.entries(path).each do |entry|
95
+ next if ['.', '..'].include?(entry)
96
+
97
+ full_path = File.join(path, entry)
98
+ archive_entry_path = File.join(archive_path, entry)
99
+ add_to_tar(tar, full_path, archive_entry_path)
100
+ end
101
+ else
102
+ # Add file
103
+ File.open(path, 'rb') do |file|
104
+ tar.add_file_simple(archive_path, File.stat(path).mode, file.size) do |tar_file|
105
+ IO.copy_stream(file, tar_file)
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ execute do |id:, source_path:, destination_path:, owner: nil|
112
+ container = ::Docker::Container.get(id)
113
+
114
+ # Verify source path exists
115
+ next "Source path not found: #{source_path}" unless File.exist?(source_path)
116
+
117
+ # Create a tar archive of the source
118
+ tar_io = StringIO.new
119
+ tar_io.set_encoding('ASCII-8BIT')
120
+
121
+ Gem::Package::TarWriter.new(tar_io) do |tar|
122
+ add_to_tar(tar, source_path, File.basename(source_path))
123
+ end
124
+
125
+ tar_io.rewind
126
+
127
+ # Copy to container
128
+ container.archive_in_stream(destination_path) do
129
+ tar_io.read
130
+ end
131
+
132
+ # Optionally change ownership
133
+ if owner
134
+ chown_path = File.join(destination_path, File.basename(source_path))
135
+ container.exec(['chown', '-R', owner, chown_path])
136
+ end
137
+
138
+ file_type = File.directory?(source_path) ? 'directory' : 'file'
139
+ response_text = "Successfully copied #{file_type} from #{source_path} to #{id}:#{destination_path}"
140
+ response_text += "\nOwnership changed to #{owner}" if owner
141
+ response_text
142
+ rescue ::Docker::Error::NotFoundError
143
+ "Container #{id} not found"
144
+ rescue StandardError => e
145
+ "Error copying to container: #{e.message}"
146
+ end
147
+ end
148
+
149
+ CopyToContainer = COPY_TO_CONTAINER_DEFINITION.to_ruby_llm_tool
150
+ end
151
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for creating Docker containers.
6
+ #
7
+ # This tool creates a new Docker container from a specified image without
8
+ # starting it. The container is created in a "created" state and can be
9
+ # started later using the start_container tool. This two-step process
10
+ # allows for container configuration before execution.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Creates containers from any available Docker image
15
+ # - Supports custom container naming
16
+ # - Configures command execution and environment variables
17
+ # - Sets up port exposure and network configuration
18
+ # - Applies advanced host configurations
19
+ # - Handles container labeling and metadata
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # Container creation is a powerful operation that can:
24
+ # - **Resource Allocation**: Consume system resources and storage
25
+ # - **Network Access**: Create network endpoints and bindings
26
+ # - **File System Access**: Mount host directories and volumes
27
+ # - **Security Context**: Run with elevated privileges if configured
28
+ #
29
+ # Implement proper access controls and resource limits.
30
+ #
31
+ # == Parameters
32
+ #
33
+ # - **image**: Docker image to use (required)
34
+ # - **name**: Custom container name (optional)
35
+ # - **cmd**: Command to execute as space-separated string (optional)
36
+ # - **env**: Environment variables as comma-separated KEY=VALUE pairs (optional)
37
+ # - **exposed_ports**: Port exposure configuration as JSON object (optional)
38
+ # - **host_config**: Advanced host configuration as JSON object (optional)
39
+ #
40
+ # == Example Usage
41
+ #
42
+ # # Simple container creation
43
+ # response = CreateContainer.call(
44
+ # server_context: context,
45
+ # image: "nginx:latest",
46
+ # name: "web-server"
47
+ # )
48
+ #
49
+ # # Advanced container with configuration
50
+ # response = CreateContainer.call(
51
+ # server_context: context,
52
+ # image: "postgres:13",
53
+ # name: "database",
54
+ # env: "POSTGRES_PASSWORD=secret,POSTGRES_DB=myapp",
55
+ # exposed_ports: {"5432/tcp" => {}},
56
+ # host_config: {
57
+ # "PortBindings" => {"5432/tcp" => [{"HostPort" => "5432"}]},
58
+ # "Binds" => ["/host/data:/var/lib/postgresql/data:rw"]
59
+ # }
60
+ # )
61
+ #
62
+ # @see ::Docker::Container.create
63
+ # @since 0.1.0
64
+ CREATE_CONTAINER_DEFINITION = ToolForge.define(:create_container) do
65
+ description 'Create a Docker container'
66
+
67
+ param :image,
68
+ type: :string,
69
+ description: 'Image name to use (e.g., "ubuntu:22.04")'
70
+
71
+ param :name,
72
+ type: :string,
73
+ description: 'Container name (optional)',
74
+ required: false
75
+
76
+ param :cmd,
77
+ type: :string,
78
+ description: 'Command to run as space-separated string (optional, e.g., "npm start" or "python app.py")',
79
+ required: false
80
+
81
+ param :env,
82
+ type: :string,
83
+ description: 'Environment variables as comma-separated KEY=VALUE pairs (optional)',
84
+ required: false
85
+
86
+ param :exposed_ports,
87
+ type: :object,
88
+ description: 'Exposed ports as {"port/protocol": {}} (optional)',
89
+ required: false
90
+
91
+ param :host_config,
92
+ type: :object,
93
+ description: 'Host configuration including port bindings, volumes, etc. (optional)',
94
+ required: false
95
+
96
+ execute do |image:, name: nil, cmd: nil, env: nil, exposed_ports: nil, host_config: nil|
97
+ config = { 'Image' => image }
98
+ config['name'] = name if name
99
+
100
+ # Parse cmd string into array if provided
101
+ config['Cmd'] = Shellwords.split(cmd) if cmd && !cmd.strip.empty?
102
+
103
+ # Parse env string into array if provided
104
+ config['Env'] = env.split(',').map(&:strip) if env && !env.strip.empty?
105
+
106
+ config['ExposedPorts'] = exposed_ports if exposed_ports
107
+ config['HostConfig'] = host_config if host_config
108
+
109
+ container = ::Docker::Container.create(config)
110
+ container_name = container.info['Names']&.first&.delete_prefix('/')
111
+
112
+ "Container created successfully. ID: #{container.id}, Name: #{container_name}"
113
+ rescue ::Docker::Error::NotFoundError
114
+ "Image #{image} not found"
115
+ rescue ::Docker::Error::ConflictError
116
+ "Container with name #{name} already exists"
117
+ rescue StandardError => e
118
+ "Error creating container: #{e.message}"
119
+ end
120
+ end
121
+
122
+ CreateContainer = CREATE_CONTAINER_DEFINITION.to_ruby_llm_tool
123
+ end
124
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for creating Docker networks.
6
+ #
7
+ # This tool provides the ability to create custom Docker networks
8
+ # for container communication and isolation. Networks enable secure
9
+ # and controlled communication between containers and external systems.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Create custom Docker networks
14
+ # - Support for multiple network drivers (bridge, overlay, host, etc.)
15
+ # - Duplicate name checking and validation
16
+ # - Network configuration and options
17
+ # - Comprehensive error handling
18
+ # - Network isolation and security controls
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Network creation involves important security considerations:
23
+ # - **Network Isolation**: Improper networks can compromise container isolation
24
+ # - **Traffic Control**: Networks affect inter-container communication
25
+ # - **External Access**: Bridge networks may expose containers externally
26
+ # - **Resource Usage**: Networks consume system resources
27
+ # - **DNS Resolution**: Custom networks affect service discovery
28
+ # - **Firewall Bypass**: Networks can bypass host firewall rules
29
+ #
30
+ # **Security Recommendations**:
31
+ # - Use appropriate network drivers for use case
32
+ # - Implement network segmentation strategies
33
+ # - Monitor network traffic and usage
34
+ # - Avoid exposing internal networks externally
35
+ # - Use network policies for access control
36
+ # - Regular audit of network configurations
37
+ #
38
+ # == Parameters
39
+ #
40
+ # - **name**: Name of the network (required)
41
+ # - **driver**: Driver to use (optional, default: "bridge")
42
+ # - **check_duplicate**: Check for networks with duplicate names (optional, default: true)
43
+ #
44
+ # == Network Drivers
45
+ #
46
+ # - **bridge**: Default driver for single-host networking
47
+ # - **overlay**: Multi-host networking for Docker Swarm
48
+ # - **host**: Uses host's network stack directly
49
+ # - **none**: Disables networking for containers
50
+ # - **macvlan**: Assigns MAC addresses to containers
51
+ #
52
+ # == Example Usage
53
+ #
54
+ # # Create basic bridge network
55
+ # response = CreateNetwork.call(
56
+ # server_context: context,
57
+ # name: "app-network"
58
+ # )
59
+ #
60
+ # # Create overlay network for swarm
61
+ # response = CreateNetwork.call(
62
+ # server_context: context,
63
+ # name: "swarm-network",
64
+ # driver: "overlay"
65
+ # )
66
+ #
67
+ # # Create network allowing duplicates
68
+ # response = CreateNetwork.call(
69
+ # server_context: context,
70
+ # name: "test-network",
71
+ # driver: "bridge",
72
+ # check_duplicate: false
73
+ # )
74
+ #
75
+ # @see ::Docker::Network.create
76
+ # @since 0.1.0
77
+ CREATE_NETWORK_DEFINITION = ToolForge.define(:create_network) do
78
+ description 'Create a Docker network'
79
+
80
+ param :name,
81
+ type: :string,
82
+ description: 'Name of the network'
83
+
84
+ param :driver,
85
+ type: :string,
86
+ description: 'Driver to use (default: bridge)',
87
+ required: false,
88
+ default: 'bridge'
89
+
90
+ param :check_duplicate,
91
+ type: :boolean,
92
+ description: 'Check for networks with duplicate names (default: true)',
93
+ required: false,
94
+ default: true
95
+
96
+ execute do |name:, driver: 'bridge', check_duplicate: true|
97
+ options = {
98
+ 'Name' => name,
99
+ 'Driver' => driver,
100
+ 'CheckDuplicate' => check_duplicate
101
+ }
102
+
103
+ network = ::Docker::Network.create(name, options)
104
+
105
+ "Network #{name} created successfully. ID: #{network.id}"
106
+ rescue ::Docker::Error::ConflictError
107
+ "Network #{name} already exists"
108
+ rescue StandardError => e
109
+ "Error creating network: #{e.message}"
110
+ end
111
+ end
112
+
113
+ CreateNetwork = CREATE_NETWORK_DEFINITION.to_ruby_llm_tool
114
+ end
115
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for creating Docker volumes.
6
+ #
7
+ # This tool provides the ability to create Docker volumes for persistent
8
+ # data storage. Volumes are essential for maintaining data across container
9
+ # lifecycles and enabling data sharing between containers.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Create named Docker volumes
14
+ # - Support for multiple volume drivers
15
+ # - Persistent data storage management
16
+ # - Volume driver configuration
17
+ # - Comprehensive error handling
18
+ # - Volume lifecycle management
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Volume creation involves important security considerations:
23
+ # - **Data Persistence**: Volumes store data beyond container lifecycle
24
+ # - **Access Control**: Volume permissions affect data security
25
+ # - **Data Isolation**: Improper volumes can compromise data separation
26
+ # - **Storage Security**: Volume drivers may have security implications
27
+ # - **Resource Usage**: Volumes consume disk space and system resources
28
+ # - **Data Leakage**: Shared volumes can expose sensitive data
29
+ #
30
+ # **Security Recommendations**:
31
+ # - Use appropriate volume drivers for security requirements
32
+ # - Implement proper access controls and permissions
33
+ # - Monitor volume usage and capacity
34
+ # - Regular backup of critical volume data
35
+ # - Audit volume access patterns
36
+ # - Use encryption for sensitive data volumes
37
+ # - Implement volume lifecycle policies
38
+ #
39
+ # == Parameters
40
+ #
41
+ # - **name**: Name of the volume (required)
42
+ # - **driver**: Driver to use (optional, default: "local")
43
+ #
44
+ # == Volume Drivers
45
+ #
46
+ # - **local**: Default driver for local filesystem storage
47
+ # - **nfs**: Network File System driver for shared storage
48
+ # - **cifs**: Common Internet File System driver
49
+ # - **rexray**: REX-Ray driver for cloud storage integration
50
+ # - **convoy**: Convoy driver for snapshot management
51
+ #
52
+ # == Example Usage
53
+ #
54
+ # # Create basic local volume
55
+ # response = CreateVolume.call(
56
+ # server_context: context,
57
+ # name: "app-data"
58
+ # )
59
+ #
60
+ # # Create volume with specific driver
61
+ # response = CreateVolume.call(
62
+ # server_context: context,
63
+ # name: "shared-storage",
64
+ # driver: "nfs"
65
+ # )
66
+ #
67
+ # # Create database volume
68
+ # response = CreateVolume.call(
69
+ # server_context: context,
70
+ # name: "postgres-data",
71
+ # driver: "local"
72
+ # )
73
+ #
74
+ # @see ::Docker::Volume.create
75
+ # @since 0.1.0
76
+ CREATE_VOLUME_DEFINITION = ToolForge.define(:create_volume) do
77
+ description 'Create a Docker volume'
78
+
79
+ param :name,
80
+ type: :string,
81
+ description: 'Name of the volume'
82
+
83
+ param :driver,
84
+ type: :string,
85
+ description: 'Driver to use (default: local)',
86
+ required: false,
87
+ default: 'local'
88
+
89
+ execute do |name:, driver: 'local'|
90
+ options = {
91
+ 'Name' => name,
92
+ 'Driver' => driver
93
+ }
94
+
95
+ ::Docker::Volume.create(name, options)
96
+
97
+ "Volume #{name} created successfully"
98
+ rescue ::Docker::Error::ConflictError
99
+ "Volume #{name} already exists"
100
+ rescue StandardError => e
101
+ "Error creating volume: #{e.message}"
102
+ end
103
+ end
104
+
105
+ CreateVolume = CREATE_VOLUME_DEFINITION.to_ruby_llm_tool
106
+ end
107
+ end