open-dock 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3cefa81ff88689e2b88ead2007ee092742f5d46
4
- data.tar.gz: 3fd0a0a696267642a7986654dbe01174f1fa3504
3
+ metadata.gz: 5b03f5d376730bd6c896aad8c253abdc81790fe6
4
+ data.tar.gz: e80058519207416314e60e131765c4ba845b8275
5
5
  SHA512:
6
- metadata.gz: 12ad80c138774601ff0215550827ffc516d0302e517f8c11fc96fc32ccdd57b88acc1141800671b421ca94f38c17f1ad9be9d1d82c0046883a41de5ed760637b
7
- data.tar.gz: a94147e0c43f7b7b79ca7ff07a62d224907608af3de1f2c3ea64b5fd7a150041f34ad8313b9fba72476aafa35abd6072c243c5aa5ab5a2a70684d3ff6704f2d8
6
+ metadata.gz: f65cec8614aecb8341b9f49ab941ff82568785fe8dc0d066c30bb1c4aa1b07bf300b37e9103727e369d48b4447c23717f09fdb9a7124ff7de33629299c51ba13
7
+ data.tar.gz: 727348c3d59295e1bcf62df4503d2717f43c9d8c018afced798386b8111189cc9fc3f76fb5bc5851f32959c73f45462cf3d8ef6e872ca3ce3f427a5677c81113
data/README.md CHANGED
@@ -23,56 +23,32 @@ Or install it yourself as:
23
23
  $ gem install open-dock
24
24
 
25
25
 
26
- ## Usage: Provision with OPS command
27
26
 
28
- OPS command is focused to cover first Provision configurations for a the Operations of your infrastructure.
29
-
30
- You can create an infrastructure project (like me [/ops](https://github.com/jlebrijo/ops))
31
-
32
- ```
33
- mkdir ops && cd ops
34
- rbenv local 2.1.2
35
- git init
36
- ```
37
-
38
- Create a Gemfile:
39
27
 
40
- ```
41
- source 'https://rubygems.org'
42
-
43
- gem 'open-dock'
28
+ ## Initialize project
44
29
 
45
- # OPTIONAL: Add next gems if you want to integrate with Chef as Configuration management tecnology
46
- gem 'knife-solo'
47
- gem 'librarian-chef'
48
- gem 'foodcritic'
49
- ```
50
-
51
- And: `bundle install`
52
-
53
- To avoid `bundle exec` repfix: `bundle install --binstubs .bundle/bin`
54
-
55
- Or integrate it within your Chef infrastructure project. Just add the gem to your Gemfile.
56
-
57
- ### Folder Structure
58
-
59
- TODO: `ops init` to create this structure
30
+ TODO: `ops init` to create folder structure and example files
60
31
 
61
32
  Structure:
62
33
 
63
34
  ```
64
35
  providers
65
- digitalocean.yml
36
+ digital_ocean.yml
37
+ google_cloud.yml
66
38
  hosts
67
39
  example.com.yml
68
40
  containers
69
41
  example.com.yml
70
42
  ```
71
43
 
72
- #### Provider file syntax
44
+ ## Configure PROVIDER
45
+
46
+ `ops list` command will list all providers suported by this gem.
73
47
 
74
48
  TODO: Create more providers (aws, linode, gcloud, ...)
75
49
 
50
+ ### Digital Ocean
51
+
76
52
  For a Digital Ocean provider create a file (ops/providers/digitalocean.yml) with your account API key:
77
53
 
78
54
  ```yml
@@ -81,11 +57,28 @@ token: a206ae60dda6bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcf0cbf41
81
57
 
82
58
  Token can be activated in your DigitaOcean console > Apps & API > Generate new token. Be sure to give write premissions.
83
59
 
84
- #### Host file syntax
60
+ ### Google Cloud
61
+
62
+ To configure Google Cloud provider create a file (ops/providers/digitalocean.yml) with these params:
63
+
64
+ ```yml
65
+ google_client_email: "850xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxtauvbl@developer.gserviceaccount.com"
66
+ google_project: "project_name"
67
+ google_key_location: "path_to_your_p12_file"
68
+ ```
69
+
70
+ You can see how to create ‘google_key_location’ and ‘google_client_email’ at https://developers.google.com/accounts/docs/OAuth2ServiceAccount#creatinganaccount
71
+
72
+ ## Configure HOST
73
+
74
+ With these files you can configure your instances/servers/droplets/ships on every provider you have configured in the last point.
75
+
76
+ ### Digital Ocean Host
85
77
 
86
78
  For a Digital Ocean host we can make the following file (ops/hosts/example.com.yml):
87
79
 
88
80
  ```yml
81
+ provider: digital_ocean
89
82
  user: core # User to connect the host
90
83
  # Values to configure DigitalOcean machine
91
84
  size: 1gb
@@ -95,9 +88,32 @@ ssh_keys:
95
88
  - e7:51:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:88:57
96
89
  ```
97
90
 
98
- And create the host: `ops create host example.com`
91
+ Helpful commands:
92
+
93
+ * `ops list digital_ocean` list all possible parameter values to use in the yml file
94
+ * `ops create example.com` will create your host
95
+
96
+ ### Google Cloud Host
97
+
98
+ For a Google Cloud host we can make the following file (ops/hosts/example.com.yml):
99
+
100
+ ```yml
101
+ provider: google_cloud
102
+ user: core # User to connect the host
103
+ # Values to configure GoogleCloud machine
104
+ machine_type: g1-small
105
+ zone_name: europe-west1-b
106
+ public_key_path: ~/.ssh/id_rsa.pub
107
+ source_image: coreos-stable-444-5-0-v20141016
108
+ disk_size_gb: 10
109
+ ```
110
+
111
+ Helpful commands:
112
+
113
+ * `ops list google_cloud` list all possible parameter values to use in the yml file
114
+ * `ops create example.com` will create your host
99
115
 
100
- ### Containers file syntax
116
+ ##Configure hosted CONTAINERS (Docker)
101
117
 
102
118
  In this file we can configure all containers to run in the host provided in the name:
103
119
 
@@ -125,27 +141,59 @@ www:
125
141
  # image: ubuntu/postgresql
126
142
  ```
127
143
 
128
- Create containers at host: `ops ship host example.com`
144
+ `ops ship example.com` will create all containers configured on 'containers/example.com.yml' file
129
145
 
130
- ### TODO: Configuration with Chef
146
+ ## TODO: Configure Containers (are nodes, with Chef)
131
147
 
132
148
  Configuration with chef commands
133
149
 
134
150
  * `ops configure CONTAINER_NAME HOST_NAME`: configure with chef a container in host. Here you need to install knife-solo gem.
135
151
  * knife solo cook [container_user]@[HOST_NAME] -p [container_ssh_port]
136
152
 
137
- ### Commands
153
+ ## Commands
138
154
 
139
155
  Create/delete domain names, create/delete hosts and ship/unship hosts:
140
156
 
157
+ * TODO: `ops init` initialize needed folders and example files
141
158
  * `ops create HOST_NAME` create the host defined by the name of the file in the 'ops/hosts' folder.
142
159
  * `ops delete HOST_NAME`
143
160
  * TODO: `ops recreate HOST_NAME` delete/create the host.
161
+ * `ops exec HOST_NAME "COMMAND"` execute any command on a host remotely (i.e. ops exec example.com 'docker ps -a')
144
162
  * `ops ship HOST_NAME` run the containers in the host.
145
163
  * `ops unship HOST_NAME`
146
164
  * TODO: `ops reship HOST_NAME` unship/ship all containers from host.
147
165
  * TODO: `ops configure CONTAINER_NAME HOST_NAME` configure container with chef.
148
166
 
167
+ ## Create your infrastructure project (/ops)
168
+
169
+ OPS command is focused to cover first Provision configurations for a the Operations of your infrastructure.
170
+
171
+ You can create an infrastructure project (like me [/ops](https://github.com/jlebrijo/ops))
172
+
173
+ ```
174
+ mkdir ops && cd ops
175
+ rbenv local 2.1.2
176
+ git init
177
+ ```
178
+
179
+ Create a Gemfile:
180
+
181
+ ```
182
+ source 'https://rubygems.org'
183
+
184
+ gem 'open-dock'
185
+
186
+ # OPTIONAL: Add next gems if you want to integrate with Chef as Configuration management tecnology
187
+ gem 'knife-solo'
188
+ gem 'librarian-chef'
189
+ gem 'foodcritic'
190
+ ```
191
+
192
+ And: `bundle install`
193
+
194
+ To avoid `bundle exec` repfix: `bundle install --binstubs .bundle/bin`
195
+
196
+ Or integrate it within your Chef infrastructure project. Just add the gem to your Gemfile.
149
197
 
150
198
  ## Contributing
151
199
 
@@ -169,4 +217,10 @@ Create/delete domain names, create/delete hosts and ship/unship hosts:
169
217
 
170
218
  * Remove create/delete domain commands
171
219
  * Remove "host" word from all commands
172
- * Remove /ops folder from providers, hosts and containers subfolders
220
+ * Remove /ops folder from providers, hosts and containers subfolders
221
+
222
+ ### v0.0.13
223
+
224
+ * Added Google Cloud as provider
225
+ * Now providers files are called underscored: digital_ocean, google_cloud ....
226
+ * In hosts YAML files we should include which provider will be built (i.e. provider: digital_ocean)
@@ -4,14 +4,7 @@ command :create do |c|
4
4
  c.description = "Creates the host described in the file #{Ops::HOSTS_DIR}/[DNS_name].yml"
5
5
  c.example "Create the host example.com in your DigitalOcean console. This is described in '#{Ops::HOSTS_DIR}/example.com.yml' like:\n # size: 512mb\n # region: ams1\n # image: coreos-stable\n # ssh_keys:\n # - e7:51:47:bc:7f:dc:2f:3c:56:65:28:e1:10:9c:88:57 xx:xx:xx:xx:xx:xx:xx", 'ops create example.com'
6
6
  c.action do |args, options|
7
- droplet = DigitalOcean::build_droplet args[0]
8
- cli = DigitalOcean::client
9
- resp = cli.droplets.create droplet
10
- if resp == droplet
11
- ip = cli.find_droplet_by_name(args[0]).networks["v4"].first.ip_address
12
- say "Droplet #{args[0]} (IP: #{ip}) succesfully created!"
13
- else
14
- raise resp
15
- end
7
+ host = Host.new args[0]
8
+ host.create
16
9
  end
17
10
  end
@@ -4,13 +4,7 @@ command :delete do |c|
4
4
  c.description = "Delete the host, based on DNS_name, which (not need but) should be described in its #{Ops::HOSTS_DIR}/[DNS_name].yml file "
5
5
  c.example 'Delete the host example.com in your DigitalOcean console', 'ops delete example.com'
6
6
  c.action do |args, options|
7
- cli = DigitalOcean::client
8
- id = cli.find_droplet_by_name(args[0]).id
9
- resp = cli.droplets.delete id: id
10
- if resp.is_a?(TrueClass)
11
- say "Droplet #{args[0]} succesfully deleted!"
12
- else
13
- raise resp
14
- end
7
+ host = Host.new args[0]
8
+ host.delete
15
9
  end
16
10
  end
@@ -1,29 +1,16 @@
1
1
  command :list do |c|
2
2
  c.summary = 'List all droplet creation parameters'
3
- c.syntax = 'ops list'
4
- c.description = "This shows a list in the format '- [id] => [description]'. Use [id] values to create your host file in #{Ops::HOSTS_DIR}[dns_name].yml "
3
+ c.syntax = 'ops list |provider|'
4
+ c.description = "List all possible providers, and all possible params for a provider if |provider| is defined"
5
+ c.example "List all possible providers", "ops list"
6
+ c.example "List all possible arguments for DigitalOcean", "ops list digital_ocean"
5
7
  c.action do |args, options|
6
- cli = DigitalOcean::client
7
- say "\nDESCRIPTION: #{c.description}\n"
8
-
9
- say "\nSizes:"
10
- cli.sizes.all.each do |i|
11
- say " - #{i.slug.ljust(6)} => $#{i.price_monthly}/mo"
12
- end
13
-
14
- say "\nRegions:"
15
- cli.regions.all.each do |i|
16
- say " - #{i.slug.ljust(6)} => #{i.name}"
8
+ if args[0]
9
+ say "\nDESCRIPTION: This shows a list in the format '- [id] => [description]'. Use [id] values to create your host file in #{Ops::HOSTS_DIR}/[dns_name].yml\n"
10
+ ProviderFactory.build(args[0]).list_params
11
+ else
12
+ ProviderFactory.list_providers
17
13
  end
18
14
 
19
- say "\nImages:"
20
- cli.images.all.each do |i|
21
- say " - #{i.slug.ljust(20)} => #{i.distribution} #{i.name}" unless i.slug.nil?
22
- end
23
-
24
- say "\nSSH Keys:"
25
- cli.ssh_keys.all.each do |i|
26
- say " - #{i.fingerprint} => #{i.name}"
27
- end
28
15
  end
29
16
  end
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'commander/import'
3
3
  require 'net/ssh'
4
4
  require 'open-dock/base'
5
- require 'open-dock/digitalocean'
5
+ require 'open-dock/providers'
6
6
  require 'open-dock/docker'
7
7
  require 'open-dock/version'
8
8
 
@@ -10,5 +10,6 @@ program :name, 'ops'
10
10
  program :version, OpenDock::VERSION
11
11
  program :description, 'Encapsulates Operations commands for complex server clouds: Provision and Configuration from all possible providers such as DigitalOcean, Google Cloud, Rackspace, Linode,...'
12
12
  program :help_formatter, :compact
13
+ program :help, 'Author', 'Juan Lebrijo <juan@lebrijo.com>'
13
14
 
14
15
  Dir.glob("#{File.dirname(__FILE__)}/commands/*.rb").each { |r| load r }
@@ -0,0 +1,65 @@
1
+ require 'yaml'
2
+ require 'active_support/inflector'
3
+
4
+ class Provider
5
+ def initialize
6
+ config_file = "#{Ops::PROVIDERS_DIR}/#{self.class.name.underscore}.yml"
7
+ begin
8
+ config = YAML.load_file config_file
9
+ rescue
10
+ raise "Please, create '#{config_file}' file following gem instrunctions"
11
+ end
12
+ create_connection config
13
+ end
14
+ def create(config)
15
+ raise "CREATE action not implemented"
16
+ end
17
+ def delete(host)
18
+ raise "DELETE action not implemented"
19
+ end
20
+ def list_params
21
+ raise "LIST PARAMS action not implemented"
22
+ end
23
+
24
+ private
25
+ def create_connection(config)
26
+ raise "PROVIDER connection should be created"
27
+ end
28
+ end
29
+
30
+ Dir.glob("#{File.dirname(__FILE__)}/providers/*.rb").each { |r| load r }
31
+
32
+ class ProviderFactory
33
+ class << self
34
+ def build(provider_name)
35
+ provider_name.classify.constantize.new
36
+ end
37
+
38
+ def list_providers
39
+ say Dir.glob("#{File.dirname(__FILE__)}/providers/*.rb").
40
+ select{|f| f.include? ".rb"}.
41
+ map{|f| f.split("/").last.split(".")[0]}.
42
+ join ", "
43
+ end
44
+ end
45
+ end
46
+
47
+ class Host
48
+ def initialize(host_name)
49
+ @host = host_name
50
+ config_file = "#{Ops::HOSTS_DIR}/#{host_name}.yml"
51
+ begin
52
+ @config = YAML.load_file "#{config_file}"
53
+ @config["name"]= host_name
54
+ rescue
55
+ raise "Please, create '#{config_file}' file with token value"
56
+ end
57
+ @provider = ProviderFactory.build @config["provider"]
58
+ end
59
+ def create
60
+ @provider.create @config
61
+ end
62
+ def delete
63
+ @provider.delete @host
64
+ end
65
+ end
@@ -0,0 +1,67 @@
1
+ require 'droplet_kit'
2
+
3
+ class DigitalOcean < Provider
4
+
5
+ def create(config)
6
+ droplet = DropletKit::Droplet.new config
7
+ resp = @connection.droplets.create droplet
8
+ if resp == droplet
9
+ ip = @connection.find_droplet_by_name(config["name"]).networks["v4"].first.ip_address
10
+ say "Droplet #{config["name"]} (IP: #{ip}) successfully created!"
11
+ else
12
+ raise resp
13
+ end
14
+ end
15
+
16
+ def delete(host)
17
+ begin
18
+ id = @connection.find_droplet_by_name(host).id
19
+ resp = @connection.droplets.delete id: id
20
+ rescue NoMethodError
21
+ raise "#{host} does not exist"
22
+ rescue
23
+ raise resp
24
+ end
25
+
26
+ if resp.is_a?(TrueClass)
27
+ say "Droplet #{host} successfully deleted!"
28
+ else
29
+ raise resp
30
+ end
31
+ end
32
+
33
+ def list_params
34
+ say "\nSizes:"
35
+ @connection.sizes.all.each do |i|
36
+ say " - #{i.slug.ljust(6)} => $#{i.price_monthly}/mo"
37
+ end
38
+
39
+ say "\nRegions:"
40
+ @connection.regions.all.each do |i|
41
+ say " - #{i.slug.ljust(6)} => #{i.name}"
42
+ end
43
+
44
+ say "\nImages:"
45
+ @connection.images.all.each do |i|
46
+ say " - #{i.slug.ljust(20)} => #{i.distribution} #{i.name}" unless i.slug.nil?
47
+ end
48
+
49
+ say "\nSSH Keys:"
50
+ @connection.ssh_keys.all.each do |i|
51
+ say " - #{i.fingerprint} => #{i.name}"
52
+ end
53
+ end
54
+
55
+ private
56
+ def create_connection(config)
57
+ @connection = DropletKit::Client.new(access_token: config["token"])
58
+ end
59
+ end
60
+
61
+ module DropletKit
62
+ class Client
63
+ def find_droplet_by_name(host_name)
64
+ self.droplets.all.find{|d| d.name == host_name}
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,65 @@
1
+ require "fog"
2
+ require "google/api_client"
3
+ Fog::VERSION=1
4
+ I18n.enforce_available_locales = false
5
+
6
+ class GoogleCloud < Provider
7
+
8
+ def create(config)
9
+ say "Creating Disk and Server instance, please wait ..."
10
+ disk = @connection.disks.create name: config["name"].parameterize,
11
+ size_gb: config["disk_size_gb"],
12
+ zone_name: config["zone_name"],
13
+ source_image: config["source_image"]
14
+
15
+ server = @connection.servers.bootstrap name: config["name"].parameterize,
16
+ machine_type: config["machine_type"],
17
+ zone_name: config["zone_name"],
18
+ disks: [disk.get_as_boot_disk(true)],
19
+ user: config["user"],
20
+ public_key_path: File.expand_path(config["public_key_path"])
21
+ server.set_disk_auto_delete true, server.disks[0]["deviceName"]
22
+
23
+ ip = server.network_interfaces[0]["accessConfigs"][0]["natIP"]
24
+ say "Instance #{config["name"]} (IP: #{ip}) successfully created!"
25
+ end
26
+
27
+ def delete(host)
28
+ server = @connection.servers.get(host.parameterize)
29
+ if server
30
+ server.destroy
31
+ say "Instance #{host} successfully deleted!"
32
+ else
33
+ raise "Instance #{host} does not exist in your Google account"
34
+ end
35
+ end
36
+
37
+ def list_params
38
+ say "\nZones"
39
+ @connection.zones.each do |i|
40
+ say " - #{i.name}"
41
+ end
42
+
43
+ say "\nMachine types:"
44
+ @connection.flavors.group_by(&:zone).each do |zone, flavors|
45
+ say " Zone #{zone}:"
46
+ flavors.each do |i|
47
+ say " - #{i.name.ljust(16)} => #{i.description}"
48
+ end
49
+ end
50
+
51
+ say "\nImages:"
52
+ @connection.images.select{|z| z.deprecated.nil?}.each do |i|
53
+ say " - #{i.name.ljust(40)} => #{i.description}\n"
54
+ end
55
+
56
+ end
57
+
58
+ private
59
+ def create_connection(config)
60
+ @connection = Fog::Compute.new provider: "Google",
61
+ google_client_email: config["google_client_email"],
62
+ google_project: config["google_project"],
63
+ google_key_location: config["google_key_location"]
64
+ end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module OpenDock
2
- VERSION = "0.0.12"
2
+ VERSION = "0.0.13"
3
3
  end
@@ -24,4 +24,6 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_runtime_dependency "commander"
26
26
  spec.add_runtime_dependency "droplet_kit"
27
+ spec.add_runtime_dependency "fog"
28
+ spec.add_runtime_dependency "google-api-client"
27
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open-dock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Lebrijo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-18 00:00:00.000000000 Z
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fog
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: google-api-client
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  description: 'Encapsulates Operations commands for complex server clouds: Provision
70
98
  and Configuration from all possible providers such as DigitalOcean, Google Cloud,
71
99
  Rackspace, Linode,...'
@@ -91,9 +119,11 @@ files:
91
119
  - lib/open-dock/commands/provision_host.rb
92
120
  - lib/open-dock/commands/ship_host.rb
93
121
  - lib/open-dock/commands/unship_host.rb
94
- - lib/open-dock/digitalocean.rb
95
122
  - lib/open-dock/docker.rb
96
123
  - lib/open-dock/ops.rb
124
+ - lib/open-dock/providers.rb
125
+ - lib/open-dock/providers/digital_ocean.rb
126
+ - lib/open-dock/providers/google_cloud.rb
97
127
  - lib/open-dock/version.rb
98
128
  - lib/tasks/.gitkeep
99
129
  - open-dock.gemspec
@@ -1,33 +0,0 @@
1
- require 'droplet_kit'
2
- require 'yaml'
3
-
4
- module DigitalOcean
5
- CONFIG_FILE = "#{Ops::PROVIDERS_DIR}/digitalocean.yml"
6
-
7
- def self.client
8
- begin
9
- config = YAML.load_file CONFIG_FILE
10
- rescue
11
- raise "Please, create '#{CONFIG_FILE}' file with token value"
12
- end
13
- DropletKit::Client.new(access_token: config["token"])
14
- end
15
-
16
- def self.build_droplet(host_name)
17
- begin
18
- params = YAML.load_file "#{Ops::HOSTS_DIR}/#{host_name}.yml"
19
- params["name"]= host_name
20
- rescue
21
- raise "Please, create '#{CONFIG_FILE}' file with token value"
22
- end
23
- DropletKit::Droplet.new params
24
- end
25
- end
26
-
27
- module DropletKit
28
- class Client
29
- def find_droplet_by_name(host_name)
30
- self.droplets.all.find{|d| d.name == host_name}
31
- end
32
- end
33
- end