lita-digitalocean 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ module Lita
2
+ module Handlers
3
+ class Digitalocean < Handler
4
+ class Region < Base
5
+ do_route /^do\s+regions?\s+list$/i, :list, {
6
+ t("help.regions.list_key") => t("help.regions.list_value")
7
+ }
8
+
9
+ def list(response)
10
+ do_response = do_call(response) do |client|
11
+ client.regions.list
12
+ end or return
13
+
14
+ messages = do_response[:regions].map { |region| t("regions.details", region) }
15
+
16
+ response.reply(*messages)
17
+ end
18
+ end
19
+
20
+ Lita.register_handler(Region)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Lita
2
+ module Handlers
3
+ class Digitalocean < Handler
4
+ class Size < Base
5
+ do_route /^do\s+sizes\s+list$/, :list, {
6
+ t("help.sizes.list_key") => t("help.sizes.list_value")
7
+ }
8
+
9
+ def list(response)
10
+ do_response = do_call(response) do |client|
11
+ client.sizes.list
12
+ end or return
13
+
14
+ messages = do_response[:sizes].map { |size| t("sizes.details", size) }
15
+
16
+ response.reply(*messages)
17
+ end
18
+ end
19
+
20
+ Lita.register_handler(Size)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,94 @@
1
+ module Lita
2
+ module Handlers
3
+ class Digitalocean < Handler
4
+ class SSHKey < Base
5
+ do_route /^do\s+ssh\s+keys?\s+add\s+.+$/i, :add, {
6
+ t("help.ssh_keys.add_key") => t("help.ssh_keys.add_value")
7
+ }
8
+
9
+ do_route /^do\s+ssh\s+keys?\s+delete\s+(\d+)$/i, :delete, {
10
+ t("help.ssh_keys.delete_key") => t("help.ssh_keys.delete_value")
11
+ }
12
+
13
+ do_route /^do\s+ssh\s+keys?\s+edit\s+(\d+)\s+.+$/i, :edit, {
14
+ t("help.ssh_keys.edit_key") => t("help.ssh_keys.edit_value")
15
+ }, { name: {}, public_key: {} }
16
+
17
+ do_route /^do\s+ssh\s+keys?\s+list$/i, :list, {
18
+ t("help.ssh_keys.list_key") => t("help.ssh_keys.list_value")
19
+ }
20
+
21
+ do_route /^do\s+ssh\s+keys?\s+show\s+(\d+)$/i, :show, {
22
+ t("help.ssh_keys.show_key") => t("help.ssh_keys.show_value"),
23
+ }
24
+
25
+ def add(response)
26
+ name, public_key = response.args[3..4]
27
+
28
+ unless name && public_key
29
+ return response.reply("#{t('format')}: #{t('help.ssh_keys.add_key')}")
30
+ end
31
+
32
+ do_response = do_call(response) do |client|
33
+ client.ssh_keys.add(name: name, ssh_pub_key: public_key)
34
+ end or return
35
+
36
+ response.reply(t("ssh_keys.add.created", do_response[:ssh_key]))
37
+ end
38
+
39
+ def delete(response)
40
+ key_id = response.matches[0][0]
41
+
42
+ do_call(response) do |client|
43
+ client.ssh_keys.delete(key_id)
44
+ end or return
45
+
46
+ response.reply(t("ssh_keys.delete.deleted", key_id: key_id))
47
+ end
48
+
49
+ def edit(response)
50
+ kwargs = {}
51
+
52
+ if (name = response.extensions[:kwargs][:name])
53
+ kwargs[:name] = name
54
+ end
55
+
56
+ if (public_key = response.extensions[:kwargs][:public_key])
57
+ kwargs[:ssh_pub_key] = public_key
58
+ end
59
+
60
+ do_response = do_call(response) do |client|
61
+ client.ssh_keys.edit(response.matches[0][0], kwargs)
62
+ end or return
63
+
64
+ response.reply(t("ssh_keys.edit.updated", do_response[:ssh_key]))
65
+ end
66
+
67
+ def list(response)
68
+ do_response = do_call(response) do |client|
69
+ client.ssh_keys.list
70
+ end or return
71
+
72
+ if do_response[:ssh_keys].empty?
73
+ response.reply(t("ssh_keys.list.empty"))
74
+ else
75
+ do_response[:ssh_keys].each do |key|
76
+ response.reply("#{key[:id]} (#{key[:name]})")
77
+ end
78
+ end
79
+ end
80
+
81
+ def show(response)
82
+ do_response = do_call(response) do |client|
83
+ client.ssh_keys.show(response.matches[0][0])
84
+ end or return
85
+
86
+ key = do_response[:ssh_key]
87
+ response.reply("#{key[:id]} (#{key[:name]}): #{key[:ssh_pub_key]}")
88
+ end
89
+ end
90
+
91
+ Lita.register_handler(SSHKey)
92
+ end
93
+ end
94
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-digitalocean"
3
- spec.version = "0.0.1"
3
+ spec.version = "1.0.0"
4
4
  spec.authors = ["Jimmy Cuadra"]
5
5
  spec.email = ["jimmy@jimmycuadra.com"]
6
6
  spec.description = %q{A Lita handler for managing DigitalOcean services.}
@@ -14,8 +14,9 @@ Gem::Specification.new do |spec|
14
14
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
15
  spec.require_paths = ["lib"]
16
16
 
17
- spec.add_runtime_dependency "lita", ">= 3.1"
18
- spec.add_runtime_dependency "digital_ocean", ">= 1.3.0"
17
+ spec.add_runtime_dependency "lita", ">= 3.2"
18
+ spec.add_runtime_dependency "lita-keyword-arguments"
19
+ spec.add_runtime_dependency "digital_ocean", ">= 1.5.0"
19
20
 
20
21
  spec.add_development_dependency "bundler", "~> 1.3"
21
22
  spec.add_development_dependency "rake"
data/locales/en.yml CHANGED
@@ -5,26 +5,163 @@ en:
5
5
  credentials_missing: >-
6
6
  client_id and api_key must be set in Lita's configuration to
7
7
  use the DigitalOcean commands.
8
+ domains:
9
+ create:
10
+ created: "Created new DNS record set for %{name}."
11
+ delete:
12
+ deleted: "Deleted DNS record set."
13
+ list:
14
+ detail: "ID: %{id}, Name: %{name}"
15
+ show:
16
+ details: >-
17
+ ID: %{id}, Name: %{name}, TTL: %{ttl}, Live Zone File: %{live_zone_file},
18
+ Error: %{error}, Zone File With Error: %{zone_file_with_error}
19
+ domain_records:
20
+ create:
21
+ created: "Created new DNS record: %{id}"
22
+ delete:
23
+ deleted: "Deleted DNS record."
24
+ edit:
25
+ updated: "Updated DNS record."
26
+ list:
27
+ detail: "ID: %{id}, Record Type: %{record_type}, Data: %{data}"
28
+ show:
29
+ details: >-
30
+ ID: %{id}, Record Type: %{record_type}, Data: %{data}, Name: %{name},
31
+ Priority: %{priority}, Port: %{port}, Weight: %{weight}
32
+ droplets:
33
+ create:
34
+ created: "Created new droplet: %{id} (%{name})"
35
+ delete:
36
+ deleted: "Deleted droplet: %{id}"
37
+ list:
38
+ detail: "ID: %{id}, Name: %{name}, IP: %{ip_address}"
39
+ password_reset:
40
+ reset: "Password reset for droplet: %{id}"
41
+ power_cycle:
42
+ cycled: "Power cycled for droplet: %{id}"
43
+ power_off:
44
+ powered_off: "Powered off droplet: %{id}"
45
+ power_on:
46
+ powered_on: "Powered on droplet: %{id}"
47
+ reboot:
48
+ rebooted: "Rebooted droplet: %{id}"
49
+ rebuild:
50
+ rebuilt: "Rebuilt droplet: %{id}"
51
+ resize:
52
+ resized: "Resized droplet: %{id}"
53
+ restore:
54
+ restored: "Restored droplet: %{id}"
55
+ show:
56
+ details: >-
57
+ ID: %{id}, Image ID: %{image_id}, Name: %{name}, Region ID: %{region_id}, Size ID:
58
+ %{size_id}, Backups active: %{backups_active}, Backups: %{formatted_backups},
59
+ Snapshots: %{formatted_snapshots}, IP address: %{ip_address}, Private IP address:
60
+ %{private_ip_address}, Locked: %{locked}, Status: %{status}
61
+ shutdown:
62
+ shut_down: "Shut down droplet: %{id}"
63
+ snapshot:
64
+ snapshotted: "Snapshotted droplet: %{id}"
8
65
  error: "DigitalOcean API error: %{message}"
9
66
  format: Format
10
67
  help:
68
+ domains:
69
+ create_key: do domains create NAME IP
70
+ create_value: Creates a new DNS record set for domain NAME and IP.
71
+ delete_key: do domains delete DOMAIN_NAME_OR_ID
72
+ delete_value: Deletes the DNS record set for domain DOMAIN_NAME_OR_ID.
73
+ list_key: do domains list
74
+ list_value: Lists all DNS record sets.
75
+ show_key: do domains show DOMAIN_NAME_OR_ID
76
+ show_value: Shows the DNS record set details for domain DOMAIN_NAME_OR_ID.
77
+ domain_records:
78
+ create_key: >-
79
+ do domain records create DOMAIN_NAME_OR_ID TYPE DATA [--name NAME]
80
+ [--priority PRIORITY] [--port PORT] [--weight WEIGHT]
81
+ create_value: Creates a new DNS record for domain DOMAIN_NAME_OR_ID.
82
+ delete_key: do domain records delete DOMAIN_NAME_OR_ID DOMAIN_RECORD_ID
83
+ delete_value: Deletes the DNS record DOMAIN_RECORD_ID for domain DOMAIN_NAME_OR_ID.
84
+ edit_key: >-
85
+ do domain records edit DOMAIN_NAME_OR_ID DOMAIN_RECORD_ID TYPE DATA [--name NAME]
86
+ [--priority PRIORITY] [--port PORT] [--weight WEIGHT]
87
+ edit_value: Edits DNS record DOMAIN_RECORD_ID for domain DOMAIN_NAME_OR_ID.
88
+ list_key: do domain records list DOMAIN_NAME_OR_ID
89
+ list_value: Lists all DNS records for domain DOMAIN_NAME_OR_ID.
90
+ show_key: do domain records show DOMAIN_NAME_OR_ID DOMAIN_RECORD_ID
91
+ show_value: Shows DNS record DOMAIN_RECORD_ID for domain DOMAIN_NAME_OR_ID.
92
+ droplets:
93
+ create_key: >-
94
+ do droplets create HOSTNAME SIZE_ID_OR_SLUG IMAGE_ID_OR_SLUG REGION_ID_OR_SLUG
95
+ [--ssh-key-ids SSH_KEY_IDS] [--private-networking] [--backups-enabled]
96
+ create_value: >-
97
+ Creates a droplet. The optional ssh_key_ids field is a comma-separated list of
98
+ SSH key IDs.
99
+ delete_key: do droplets delete ID [--scrub]
100
+ delete_value: Deletes a droplet, optionally writing zeroes to the disk first.
101
+ list_key: do droplets list
102
+ list_value: Lists all droplets.
103
+ password_reset_key: do droplets password reset ID
104
+ password_reset_value: Resets the root password for a droplet.
105
+ power_cycle_key: do droplets power cycle ID
106
+ power_cycle_value: Powers off and then powers on a droplet.
107
+ power_off_key: do droplets power off ID
108
+ power_off_value: Powers off a droplet.
109
+ power_on_key: do droplets power on ID
110
+ power_on_value: Powers on a droplet.
111
+ reboot_key: do droplets reboot ID
112
+ reboot_value: Reboots a droplet.
113
+ resize_key: do droplets resize ID SIZE_ID_OR_SLUG
114
+ resize_value: Resizes a droplet.
115
+ restore_key: do droplets restore ID IMAGE_ID
116
+ restore_value: Restores a droplet from an image.
117
+ show_key: do droplets show ID
118
+ show_value: Shows the details of a droplet.
119
+ shutdown_key: do droplets shutdown ID
120
+ shutdown_value: Shuts down a droplet.
121
+ snapshot_key: do droplets snapshot ID [NAME]
122
+ snapshot_value: Takes a snapshot of a droplet, optionally naming the snapshot.
123
+ images:
124
+ delete_key: do images delete ID_OR_SLUG
125
+ delete_value: Deletes an image with the given ID or slug.
126
+ list_key: "do images list [FILTER]"
127
+ list_value: >-
128
+ Lists available images, optionally filtered by FILTER ("global" or "my_images").
129
+ show_key: do images show ID_OR_SLUG
130
+ show_value: Shows the details of an image with the given ID or slug.
131
+ regions:
132
+ list_key: do regions list
133
+ list_value: Lists all available regions.
11
134
  ssh_keys:
12
135
  add_key: do ssh keys add NAME PUBLIC_KEY
13
136
  add_value: Adds a new SSH key.
14
137
  delete_key: do ssh keys delete ID
15
- delete_value: Delete the SSH key with the given ID.
16
- edit_key: "do ssh keys edit ID [name=NAME] [public_key=PUBLIC_KEY]"
17
- edit_value: Change the NAME and/or PUBLIC_KEY of the SSH key with the given ID.
138
+ delete_value: Deletes the SSH key with the given ID.
139
+ edit_key: "do ssh keys edit ID [--name NAME] [--public-key PUBLIC_KEY]"
140
+ edit_value: Changes the NAME and/or PUBLIC_KEY of the SSH key with the given ID.
18
141
  list_key: do ssh keys list
19
142
  list_value: Lists all SSH keys.
20
143
  show_key: do ssh keys show ID
21
144
  show_value: Shows the public key for SSH key with the given ID.
145
+ sizes:
146
+ list_key: do sizes list
147
+ list_value: Lists all the possible image sizes.
148
+ images:
149
+ details: >-
150
+ ID: %{id}, Name: %{name}, Slug: %{slug}, Distribution: %{distribution},
151
+ Public: %{public}, Regions: %{formatted_regions},
152
+ Region Slugs: %{formatted_region_slugs}
153
+ delete:
154
+ deleted: "Deleted image: %{image_id}"
155
+ regions:
156
+ details: "ID: %{id}, Name: %{name}, Slug: %{slug}"
157
+ sizes:
158
+ details: "ID: %{id}, Name: %{name}, Slug: %{slug}"
22
159
  ssh_keys:
23
160
  add:
24
- created: "Created new SSH key: %{message}"
161
+ created: "Created new SSH key: %{id} (%{name}): %{ssh_pub_key}"
25
162
  delete:
26
163
  deleted: "Deleted SSH key: %{key_id}"
27
164
  edit:
28
- updated: "Updated SSH key: %{message}"
165
+ updated: "Updated SSH key: %{id} (%{name}): %{ssh_pub_key}"
29
166
  list:
30
167
  empty: No SSH keys have been added yet.
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ handler_class = Class.new(Lita::Handlers::Digitalocean::Base) do
4
+ route /do droplets list/, :list, command: true
5
+
6
+ def self.default_config(config)
7
+ end
8
+
9
+ def list(response)
10
+ do_call(response) do |client|
11
+ { status: "error", message: "Something went wrong" }
12
+ end
13
+ end
14
+ end
15
+
16
+ describe handler_class, lita_handler: true do
17
+ describe "#do_call" do
18
+ it "responds with an error if the DigitalOcean API key is not set" do
19
+ send_command("do droplets list")
20
+ expect(replies.last).to include("client_id and api_key must be set")
21
+ end
22
+
23
+ it "responds with an error if the DigitalOcean client ID is not set" do
24
+ Lita.config.handlers.digitalocean.api_key = "secret"
25
+ send_command("do droplets list")
26
+ expect(replies.last).to include("client_id and api_key must be set")
27
+ end
28
+
29
+ it "responds with an error if the DigitalOcean API responds with an error" do
30
+ Lita.config.handlers.digitalocean.tap do |config|
31
+ config.api_key = "secret"
32
+ config.client_id = "secret"
33
+ end
34
+
35
+ send_command("do droplets list")
36
+ expect(replies.last).to eq("DigitalOcean API error: Something went wrong")
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,118 @@
1
+ require "spec_helper"
2
+
3
+ describe Lita::Handlers::Digitalocean::DomainRecord, lita_handler: true do
4
+ it do
5
+ routes_command(
6
+ "do domain records create example.com txt 'some value' --name example.com"
7
+ ).to(:create)
8
+ end
9
+ it { routes_command("do domain records delete example.com 123").to(:delete) }
10
+ it do
11
+ routes_command(
12
+ "do domain records edit example.com 123 txt 'some value' name=example.com"
13
+ ).to(:edit)
14
+ end
15
+ it { routes_command("do domain records list example.com").to(:list) }
16
+ it { routes_command("do domain records show example.com 123").to(:show) }
17
+
18
+ let(:client) { instance_double("::DigitalOcean::API", domains: client_domains) }
19
+ let(:client_domains) { instance_double("::DigitalOcean::Resource::Domain") }
20
+
21
+ before do
22
+ Lita.config.handlers.digitalocean = Lita::Config.new
23
+ Lita.config.handlers.digitalocean.tap do |config|
24
+ config.client_id = "CLIENT_ID"
25
+ config.api_key = "API_KEY"
26
+ end
27
+
28
+ allow(Lita::Authorization).to receive(:user_in_group?).with(
29
+ user,
30
+ :digitalocean_admins
31
+ ).and_return(true)
32
+
33
+ allow(::DigitalOcean::API).to receive(:new).and_return(client)
34
+ end
35
+
36
+ describe "#create" do
37
+ it "creates a new domain record" do
38
+ allow(client_domains).to receive(:create_record).with(
39
+ "example.com",
40
+ data: "@",
41
+ name: "foo",
42
+ port: "456",
43
+ priority: "123",
44
+ record_type: "srv",
45
+ weight: "789"
46
+ ).and_return(status: "OK", record: { id: 123 })
47
+ send_command("do domain records create example.com srv @ --name foo --priority 123 --port 456 --weight 789")
48
+ expect(replies.last).to eq("Created new DNS record: 123")
49
+ end
50
+ end
51
+
52
+ describe "#delete" do
53
+ it "deletes a domain record" do
54
+ allow(client_domains).to receive(:delete_record).with("123", "456").and_return(status: "OK")
55
+ send_command("do domain records delete 123 456")
56
+ expect(replies.last).to eq("Deleted DNS record.")
57
+ end
58
+ end
59
+
60
+ describe "#edit" do
61
+ it "edits a domain record" do
62
+ allow(client_domains).to receive(:edit_record).with(
63
+ "example.com",
64
+ "123",
65
+ data: "example.com",
66
+ record_type: "cname",
67
+ name: "www.example.com"
68
+ ).and_return(status: "OK")
69
+ send_command(
70
+ "do domain records edit example.com 123 cname example.com --name www.example.com"
71
+ )
72
+ expect(replies.last).to eq("Updated DNS record.")
73
+ end
74
+ end
75
+
76
+ describe "#list" do
77
+ it "responds with a list of all domain records for the given record set" do
78
+ allow(client_domains).to receive(:list_records).with("example.com").and_return(
79
+ status: "OK",
80
+ records: [{
81
+ id: 123,
82
+ record_type: "A",
83
+ data: "10.0.0.0"
84
+ }, {
85
+ id: 456,
86
+ record_type: "CNAME",
87
+ data: "@"
88
+ }]
89
+ )
90
+ send_command("do domain records list example.com")
91
+ expect(replies).to eq([
92
+ "ID: 123, Record Type: A, Data: 10.0.0.0",
93
+ "ID: 456, Record Type: CNAME, Data: @"
94
+ ])
95
+ end
96
+ end
97
+
98
+ describe "#show" do
99
+ it "responds with the details of the domain record" do
100
+ allow(client_domains).to receive(:show_record).with("example.com", "123").and_return(
101
+ status: "OK",
102
+ record: {
103
+ id: 123,
104
+ record_type: "A",
105
+ data: "10.0.0.0",
106
+ name: "example.com",
107
+ priority: 123,
108
+ port: 456,
109
+ weight: 789
110
+ }
111
+ )
112
+ send_command("do domain records show example.com 123")
113
+ expect(replies.last).to eq(
114
+ "ID: 123, Record Type: A, Data: 10.0.0.0, Name: example.com, Priority: 123, Port: 456, Weight: 789"
115
+ )
116
+ end
117
+ end
118
+ end