foreman_digitalocean 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/helpers/digitalocean_images_helper.rb +33 -0
- data/app/models/concerns/fog_extensions/digitalocean/image.rb +5 -2
- data/app/models/concerns/fog_extensions/digitalocean/server.rb +6 -0
- data/app/models/foreman_digitalocean/concerns/host_managed_extensions.rb +16 -0
- data/app/models/foreman_digitalocean/digitalocean.rb +25 -29
- data/app/views/compute_resources/form/_digitalocean.html.erb +10 -7
- data/app/views/compute_resources_vms/form/digitalocean/_base.html.erb +7 -12
- data/app/views/compute_resources_vms/index/_digitalocean.html.erb +3 -3
- data/app/views/images/form/_digitalocean.html.erb +5 -2
- data/lib/foreman_digitalocean/engine.rb +27 -11
- data/lib/foreman_digitalocean/tasks/test.rake +44 -0
- data/lib/foreman_digitalocean/version.rb +1 -1
- data/test/factories/compute_resources.rb +13 -0
- data/test/test_plugin_helper.rb +6 -0
- data/test/unit/foreman_digitalocean/digitalocean_test.rb +18 -0
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09968431a3ccdbbd31a0dde996cfff6358a2a254
|
4
|
+
data.tar.gz: d044e4f386bd33594bcab16953e3380f2e334de7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83c7f182dfabf192159f2c2678f9aafceaece54ba60f9d9a19d397456d54c6c969a588242b25df274b5e349e3dd21bd77dff86324c867a9df36e06715ca94a7d
|
7
|
+
data.tar.gz: 9a861c05403d615412a39530860cca00cc2193bd921aaee5ea9d63dd2b34fd2315e5208ab46d78685720a30b8803b3289a0258bb658dc38cd0af7d12bf336f8a
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DigitaloceanImagesHelper
|
2
|
+
def digitalocean_image_field(f)
|
3
|
+
images = @compute_resource.available_images
|
4
|
+
images.each { |image| image.name = image.id if image.name.nil? }
|
5
|
+
select_f f, :uuid, images.to_a.sort_by(&:full_name),
|
6
|
+
:id, :full_name, {}, :label => _('Image')
|
7
|
+
end
|
8
|
+
|
9
|
+
def select_image(f, compute_resource)
|
10
|
+
images = possible_images(compute_resource, nil, nil)
|
11
|
+
|
12
|
+
select_f(f,
|
13
|
+
:image_id,
|
14
|
+
images,
|
15
|
+
:id,
|
16
|
+
:slug,
|
17
|
+
{ :include_blank => (images.empty? || images.size == 1) ? false : _('Please select an image') },
|
18
|
+
{ :label => ('Image'), :disabled => images.empty? } )
|
19
|
+
end
|
20
|
+
|
21
|
+
def select_region(f, compute_resource)
|
22
|
+
regions = compute_resource.regions
|
23
|
+
f.object.region = compute_resource.region
|
24
|
+
select_f(f,
|
25
|
+
:region,
|
26
|
+
regions,
|
27
|
+
:slug,
|
28
|
+
:slug,
|
29
|
+
{},
|
30
|
+
:label => ('Region'),
|
31
|
+
:disabled => compute_resource.images.empty?)
|
32
|
+
end
|
33
|
+
end
|
@@ -23,9 +23,12 @@ module FogExtensions
|
|
23
23
|
# Attempt guessing arch based on the name from digital ocean
|
24
24
|
def arch
|
25
25
|
requires :os_version
|
26
|
-
os_version.end_with?("x64")
|
26
|
+
if os_version.end_with?("x64")
|
27
|
+
"x86_64"
|
28
|
+
elsif os_version.end_with?("x32")
|
29
|
+
"i386"
|
30
|
+
end
|
27
31
|
end
|
28
|
-
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
@@ -3,6 +3,8 @@ module FogExtensions
|
|
3
3
|
module Server
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
attr_accessor :image_id
|
7
|
+
|
6
8
|
def identity_to_s
|
7
9
|
identity.to_s
|
8
10
|
end
|
@@ -44,6 +46,10 @@ module FogExtensions
|
|
44
46
|
[public_ip_address, private_ip_address].flatten.select(&:present?)
|
45
47
|
end
|
46
48
|
|
49
|
+
def state
|
50
|
+
requires :status
|
51
|
+
@state ||= status
|
52
|
+
end
|
47
53
|
end
|
48
54
|
end
|
49
55
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ForemanDigitalocean
|
2
|
+
module Concerns
|
3
|
+
module HostManagedExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# Rails 4 does not provide dynamic finders for delegated methods and
|
8
|
+
# the SSH orchestrate compute method uses them.
|
9
|
+
def self.find_by_ip(ip)
|
10
|
+
nic = Nic::Base.find_by_ip(ip)
|
11
|
+
nic.host if nic.present?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,24 +1,25 @@
|
|
1
1
|
module ForemanDigitalocean
|
2
2
|
class Digitalocean < ComputeResource
|
3
|
+
alias_attribute :api_key, :password
|
4
|
+
alias_attribute :region, :url
|
5
|
+
|
3
6
|
has_one :key_pair, :foreign_key => :compute_resource_id, :dependent => :destroy
|
4
7
|
delegate :flavors, :to => :client
|
5
8
|
|
6
|
-
validates :
|
9
|
+
validates :api_key, :presence => true
|
7
10
|
before_create :test_connection
|
8
11
|
|
9
12
|
after_create :setup_key_pair
|
10
13
|
after_destroy :destroy_key_pair
|
11
14
|
|
12
|
-
|
13
|
-
# Not sure why it would need a url, but OK (copied from ec2)
|
14
|
-
alias_attribute :region, :url
|
15
|
+
attr_accessible :region, :api_key
|
15
16
|
|
16
17
|
def to_label
|
17
18
|
"#{name} (#{provider_friendly_name})"
|
18
19
|
end
|
19
20
|
|
20
21
|
def provided_attributes
|
21
|
-
super.merge(
|
22
|
+
super.merge(:uuid => :identity_to_s, :ip => :public_ip_address)
|
22
23
|
end
|
23
24
|
|
24
25
|
def self.model_name
|
@@ -35,8 +36,9 @@ module ForemanDigitalocean
|
|
35
36
|
raise(ActiveRecord::RecordNotFound)
|
36
37
|
end
|
37
38
|
|
38
|
-
def create_vm(args = {
|
39
|
+
def create_vm(args = {})
|
39
40
|
args["ssh_keys"] = [ssh_key] if ssh_key
|
41
|
+
args['image'] = args['image_id']
|
40
42
|
super(args)
|
41
43
|
rescue Fog::Errors::Error => e
|
42
44
|
logger.error "Unhandled DigitalOcean error: #{e.class}:#{e.message}\n " + e.backtrace.join("\n ")
|
@@ -48,13 +50,13 @@ module ForemanDigitalocean
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def regions
|
51
|
-
return [] if
|
53
|
+
return [] if api_key.blank?
|
52
54
|
client.regions
|
53
55
|
end
|
54
56
|
|
55
57
|
def test_connection(options = {})
|
56
58
|
super
|
57
|
-
errors[:
|
59
|
+
errors[:password].empty? && regions.count
|
58
60
|
rescue Excon::Errors::Unauthorized => e
|
59
61
|
errors[:base] << e.response.body
|
60
62
|
rescue Fog::Errors::Error => e
|
@@ -63,12 +65,12 @@ module ForemanDigitalocean
|
|
63
65
|
|
64
66
|
def destroy_vm(uuid)
|
65
67
|
vm = find_vm_by_uuid(uuid)
|
66
|
-
vm.
|
68
|
+
vm.delete if vm.present?
|
67
69
|
true
|
68
70
|
end
|
69
71
|
|
70
72
|
# not supporting update at the moment
|
71
|
-
def update_required?(
|
73
|
+
def update_required?(*)
|
72
74
|
false
|
73
75
|
end
|
74
76
|
|
@@ -77,7 +79,8 @@ module ForemanDigitalocean
|
|
77
79
|
end
|
78
80
|
|
79
81
|
def associated_host(vm)
|
80
|
-
Host.authorized(:view_hosts, Host).
|
82
|
+
Host.authorized(:view_hosts, Host).
|
83
|
+
where(:ip => [vm.public_ip_address, vm.private_ip_address]).first
|
81
84
|
end
|
82
85
|
|
83
86
|
def user_data_supported?
|
@@ -85,7 +88,7 @@ module ForemanDigitalocean
|
|
85
88
|
end
|
86
89
|
|
87
90
|
def default_region_name
|
88
|
-
@default_region_name ||= client.regions
|
91
|
+
@default_region_name ||= client.regions[region.to_i].try(:name)
|
89
92
|
rescue Excon::Errors::Unauthorized => e
|
90
93
|
errors[:base] << e.response.body
|
91
94
|
end
|
@@ -95,25 +98,24 @@ module ForemanDigitalocean
|
|
95
98
|
def client
|
96
99
|
@client ||= Fog::Compute.new(
|
97
100
|
:provider => "DigitalOcean",
|
98
|
-
:
|
99
|
-
:
|
101
|
+
:version => 'V2',
|
102
|
+
:digitalocean_token => api_key
|
100
103
|
)
|
101
104
|
end
|
102
105
|
|
103
106
|
def vm_instance_defaults
|
104
107
|
super.merge(
|
105
|
-
:
|
108
|
+
:size => client.flavors.first.slug
|
106
109
|
)
|
107
110
|
end
|
108
111
|
|
109
|
-
|
110
|
-
#
|
111
|
-
# it should create the key and upload it to DigitalOcean
|
112
|
+
# Creates a new key pair for each new DigitalOcean compute resource
|
113
|
+
# After creating the key, it uploads it to DigitalOcean
|
112
114
|
def setup_key_pair
|
113
115
|
public_key, private_key = generate_key
|
114
116
|
key_name = "foreman-#{id}#{Foreman.uuid}"
|
115
|
-
|
116
|
-
KeyPair.create! :name => key_name, :compute_resource_id =>
|
117
|
+
client.create_ssh_key key_name, public_key
|
118
|
+
KeyPair.create! :name => key_name, :compute_resource_id => id, :secret => private_key
|
117
119
|
rescue => e
|
118
120
|
logger.warn "failed to generate key pair"
|
119
121
|
logger.error e.message
|
@@ -134,24 +136,18 @@ module ForemanDigitalocean
|
|
134
136
|
|
135
137
|
def ssh_key
|
136
138
|
@ssh_key ||= begin
|
137
|
-
key = client.list_ssh_keys.data[:body]["ssh_keys"].
|
138
|
-
if key
|
139
|
-
#the vm creator expects objects which respond to id, OpenStruct is the shortest solution.
|
140
|
-
OpenStruct.new(key)
|
141
|
-
else
|
142
|
-
nil
|
143
|
-
end
|
139
|
+
key = client.list_ssh_keys.data[:body]["ssh_keys"].find { |i| i["name"] == key_pair.name }
|
140
|
+
key['id'] if key.present?
|
144
141
|
end
|
145
142
|
end
|
146
143
|
|
147
144
|
def generate_key
|
148
145
|
key = OpenSSL::PKey::RSA.new 2048
|
149
146
|
type = key.ssh_type
|
150
|
-
data = [
|
147
|
+
data = [key.to_blob].pack('m0')
|
151
148
|
|
152
149
|
openssh_format_public_key = "#{type} #{data}"
|
153
150
|
[openssh_format_public_key, key.to_pem]
|
154
151
|
end
|
155
|
-
|
156
152
|
end
|
157
153
|
end
|
@@ -1,11 +1,14 @@
|
|
1
|
-
<%=
|
2
|
-
<%= password_f f, :password, :label => _("API Key") %>
|
3
|
-
|
1
|
+
<%= password_f f, :api_key, :label => _("API Key"), :unset => unset_password? %>
|
4
2
|
<% regions = f.object.regions rescue [] %>
|
5
3
|
|
6
4
|
<div id='region_selection'>
|
7
|
-
<%= select_f(
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
<%= select_f(
|
6
|
+
f, :region, regions, :slug, :name, {},
|
7
|
+
:label => _('Default Region'), :disabled => regions.empty?,
|
8
|
+
:help_inline => link_to_function(
|
9
|
+
regions.empty? ? _("Load Regions") : _("Test Connection"), "testConnection(this)",
|
10
|
+
:class => "btn + #{regions.empty? ? "btn-default" : "btn-success"}",
|
11
|
+
:'data-url' => test_connection_compute_resources_path) +
|
12
|
+
spinner('', :id => 'test_connection_indicator',
|
13
|
+
:class => 'hide').html_safe) %>
|
11
14
|
</div>
|
@@ -1,12 +1,7 @@
|
|
1
|
-
<%= select_f f, :
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
f.object.region_id = compute_resource.region
|
9
|
-
%>
|
10
|
-
|
11
|
-
<div id='image_selection'><%= select_f f, :image_id, images, :uuid, :name, { :include_blank => (images.empty? || images.size == 1) ? false : _('Please Select an Image') }, { :label => ('Image'), :disabled => images.empty? } %></div>
|
12
|
-
<div id='region_selection'><%= select_f f, :region_id, regions, :id, :name, {}, { :label => ('Region'), :disabled => images.empty?} %></div>
|
1
|
+
<%= select_f f, :size, compute_resource.flavors, :slug, :slug, {}, {:label => _('Flavor')} %>
|
2
|
+
<div id='image_selection'>
|
3
|
+
<%= select_image(f, compute_resource) %>
|
4
|
+
</div>
|
5
|
+
<div id='region_selection'>
|
6
|
+
<%= select_region(f, compute_resource) %>
|
7
|
+
</div>
|
@@ -12,9 +12,9 @@
|
|
12
12
|
<% @vms.each do |vm| %>
|
13
13
|
<tr>
|
14
14
|
<td><%= link_to_if_authorized vm.name, hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.identity).merge(:auth_object => @compute_resource, :authorizer => authorizer) %></td>
|
15
|
-
<td><%= vm.image
|
16
|
-
<td><%= vm.
|
17
|
-
<td><%= vm.region
|
15
|
+
<td><%= vm.image['slug'] if vm.image.present? %></td>
|
16
|
+
<td><%= vm.size['slug'] %></td>
|
17
|
+
<td><%= vm.region['slug'] %></td>
|
18
18
|
<td> <span <%= vm_power_class(vm.ready?) %>> <%= vm_state(vm) %></span> </td>
|
19
19
|
<td>
|
20
20
|
<%= action_buttons(
|
@@ -1,3 +1,6 @@
|
|
1
|
-
<%= text_f f,
|
2
|
-
|
1
|
+
<%= text_f f,
|
2
|
+
:username,
|
3
|
+
:value => @image.username || "root",
|
4
|
+
:help_inline => _("The user that is used to ssh into the instance, normally cloud-user, ec2-user, ubuntu, root etc") %>
|
5
|
+
<%= digitalocean_image_field(f) %>
|
3
6
|
<%= checkbox_f f, :user_data, :help_inline => _("Does this image support user data input (e.g. via cloud-init)?") %>
|
@@ -2,11 +2,11 @@ require 'fast_gettext'
|
|
2
2
|
require 'gettext_i18n_rails'
|
3
3
|
|
4
4
|
module ForemanDigitalocean
|
5
|
-
# Inherit from the Rails module of the parent app (Foreman), not the plugin.
|
6
|
-
# Thus, inherits from ::Rails::Engine and not from Rails::Engine
|
7
5
|
class Engine < ::Rails::Engine
|
8
6
|
engine_name 'foreman_digitalocean'
|
9
7
|
|
8
|
+
config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
|
9
|
+
|
10
10
|
initializer 'foreman_digitalocean.register_gettext', :after => :load_config_initializers do
|
11
11
|
locale_dir = File.join(File.expand_path('../../..', __FILE__), 'locale')
|
12
12
|
locale_domain = 'foreman_digitalocean'
|
@@ -14,19 +14,35 @@ module ForemanDigitalocean
|
|
14
14
|
Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
|
15
15
|
end
|
16
16
|
|
17
|
-
initializer 'foreman_digitalocean.register_plugin', :
|
17
|
+
initializer 'foreman_digitalocean.register_plugin', :before => :finisher_hook do
|
18
18
|
Foreman::Plugin.register :foreman_digitalocean do
|
19
19
|
requires_foreman '>= 1.8'
|
20
20
|
compute_resource ForemanDigitalocean::Digitalocean
|
21
21
|
end
|
22
22
|
end
|
23
|
-
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
rake_tasks do
|
25
|
+
load "#{ForemanDigitalocean::Engine.root}/lib/foreman_digitalocean/tasks/test.rake"
|
26
|
+
end
|
27
|
+
|
28
|
+
config.to_prepare do
|
29
|
+
require 'fog/digitalocean'
|
30
|
+
require 'fog/digitalocean/compute_v2'
|
31
|
+
require 'fog/digitalocean/models/compute_v2/image'
|
32
|
+
require 'fog/digitalocean/models/compute_v2/server'
|
33
|
+
require File.expand_path(
|
34
|
+
'../../../app/models/concerns/fog_extensions/digitalocean/server',
|
35
|
+
__FILE__)
|
36
|
+
require File.expand_path(
|
37
|
+
'../../../app/models/concerns/fog_extensions/digitalocean/image',
|
38
|
+
__FILE__)
|
39
|
+
|
40
|
+
Fog::Compute::DigitalOceanV2::Image.send :include,
|
41
|
+
FogExtensions::DigitalOcean::Image
|
42
|
+
Fog::Compute::DigitalOceanV2::Server.send :include,
|
43
|
+
FogExtensions::DigitalOcean::Server
|
44
|
+
::Host::Managed.send :include,
|
45
|
+
ForemanDigitalocean::Concerns::HostManagedExtensions
|
46
|
+
end
|
47
|
+
end
|
32
48
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path("../engine", File.dirname(__FILE__))
|
2
|
+
namespace :test do
|
3
|
+
desc "Run the plugin unit test suite."
|
4
|
+
task :digitalocean => ['db:test:prepare'] do
|
5
|
+
test_task = Rake::TestTask.new('digitalocean_test_task') do |t|
|
6
|
+
t.libs << ["test", "#{ForemanDigitalocean::Engine.root}/test"]
|
7
|
+
t.test_files = [
|
8
|
+
"#{ForemanDigitalocean::Engine.root}/test/**/*_test.rb"
|
9
|
+
]
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::Task[test_task.name].invoke
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :digitalocean do
|
18
|
+
task :rubocop do
|
19
|
+
begin
|
20
|
+
require 'rubocop/rake_task'
|
21
|
+
RuboCop::RakeTask.new(:rubocop_digitalocean) do |task|
|
22
|
+
task.patterns = ["#{ForemanDigitalocean::Engine.root}/app/**/*.rb",
|
23
|
+
"#{ForemanDigitalocean::Engine.root}/lib/**/*.rb",
|
24
|
+
"#{ForemanDigitalocean::Engine.root}/test/**/*.rb"]
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
puts "Rubocop not loaded."
|
28
|
+
end
|
29
|
+
|
30
|
+
Rake::Task['rubocop_digitalocean'].invoke
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::Task[:test].enhance do
|
35
|
+
Rake::Task['test:digitalocean'].invoke
|
36
|
+
end
|
37
|
+
|
38
|
+
load 'tasks/jenkins.rake'
|
39
|
+
if Rake::Task.task_defined?(:'jenkins:unit')
|
40
|
+
Rake::Task["jenkins:unit"].enhance do
|
41
|
+
Rake::Task['test:digitalocean'].invoke
|
42
|
+
Rake::Task['digitalocean:rubocop'].invoke
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :container_resource, :class => ComputeResource do
|
3
|
+
sequence(:name) { |n| "compute_resource#{n}" }
|
4
|
+
|
5
|
+
trait :digitalocean do
|
6
|
+
provider 'Digitalocean'
|
7
|
+
api_key 'asampleapikey'
|
8
|
+
region 'everywhere'
|
9
|
+
end
|
10
|
+
|
11
|
+
factory :digitalocean_cr, :class => ForemanDigitalocean::Digitalocean, :traits => [:digitalocean]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class ForemanDigitalocean::DigitaloceanTest < ActiveSupport::TestCase
|
4
|
+
should validate_presence_of(:api_key)
|
5
|
+
should allow_mass_assignment_of(:region)
|
6
|
+
should allow_mass_assignment_of(:api_key)
|
7
|
+
should delegate_method(:flavors).to(:client)
|
8
|
+
should have_one(:key_pair)
|
9
|
+
|
10
|
+
setup { Fog.mock! }
|
11
|
+
teardown { Fog.unmock! }
|
12
|
+
|
13
|
+
test 'ssh key pair gets created after its saved' do
|
14
|
+
digitalocean = FactoryGirl.build(:digitalocean_cr)
|
15
|
+
digitalocean.expects(:setup_key_pair)
|
16
|
+
digitalocean.save
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_digitalocean
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tommy McNeely, Daniel Lobato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -33,8 +33,10 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- LICENSE
|
35
35
|
- README.md
|
36
|
+
- app/helpers/digitalocean_images_helper.rb
|
36
37
|
- app/models/concerns/fog_extensions/digitalocean/image.rb
|
37
38
|
- app/models/concerns/fog_extensions/digitalocean/server.rb
|
39
|
+
- app/models/foreman_digitalocean/concerns/host_managed_extensions.rb
|
38
40
|
- app/models/foreman_digitalocean/digitalocean.rb
|
39
41
|
- app/views/api/v1/compute_resources/digitalocean.json
|
40
42
|
- app/views/api/v2/compute_resources/digitalocean.json
|
@@ -46,8 +48,12 @@ files:
|
|
46
48
|
- app/views/images/form/_digitalocean.html.erb
|
47
49
|
- lib/foreman_digitalocean.rb
|
48
50
|
- lib/foreman_digitalocean/engine.rb
|
51
|
+
- lib/foreman_digitalocean/tasks/test.rake
|
49
52
|
- lib/foreman_digitalocean/version.rb
|
50
53
|
- locale/Makefile
|
54
|
+
- test/factories/compute_resources.rb
|
55
|
+
- test/test_plugin_helper.rb
|
56
|
+
- test/unit/foreman_digitalocean/digitalocean_test.rb
|
51
57
|
homepage: http://github.com/theforeman/foreman-digitalocean
|
52
58
|
licenses:
|
53
59
|
- GPL-3
|
@@ -72,4 +78,7 @@ rubygems_version: 2.2.2
|
|
72
78
|
signing_key:
|
73
79
|
specification_version: 4
|
74
80
|
summary: Provision and manage DigitalOcean droplets from Foreman
|
75
|
-
test_files:
|
81
|
+
test_files:
|
82
|
+
- test/factories/compute_resources.rb
|
83
|
+
- test/test_plugin_helper.rb
|
84
|
+
- test/unit/foreman_digitalocean/digitalocean_test.rb
|