foreman_docker 0.0.3 → 0.1.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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -2
  3. data/Rakefile +13 -2
  4. data/app/assets/stylesheets/foreman_docker/terminal.css.scss +85 -0
  5. data/app/controllers/containers/steps_controller.rb +55 -0
  6. data/app/controllers/containers_controller.rb +62 -0
  7. data/app/helpers/container_steps_helper.rb +11 -0
  8. data/app/helpers/containers_helper.rb +54 -0
  9. data/app/models/concerns/fog_extensions/fogdocker/image.rb +1 -2
  10. data/app/models/concerns/fog_extensions/fogdocker/server.rb +18 -8
  11. data/app/models/container.rb +29 -0
  12. data/app/models/docker_image.rb +7 -0
  13. data/app/models/docker_tag.rb +7 -0
  14. data/app/models/foreman_docker/docker.rb +22 -16
  15. data/app/views/api/v1/compute_resources/docker.json +1 -0
  16. data/app/views/api/v2/compute_resources/docker.json +1 -0
  17. data/app/views/compute_resources/form/_docker.html.erb +8 -1
  18. data/app/views/compute_resources_vms/show/_docker.html.erb +4 -0
  19. data/app/views/containers/_list.html.erb +35 -0
  20. data/app/views/containers/index.html.erb +31 -0
  21. data/app/views/containers/show.html.erb +104 -0
  22. data/app/views/containers/steps/_form_buttons.html.erb +20 -0
  23. data/app/views/containers/steps/_title.html.erb +3 -0
  24. data/app/views/containers/steps/configuration.html.erb +14 -0
  25. data/app/views/containers/steps/environment.html.erb +9 -0
  26. data/app/views/containers/steps/image.html.erb +33 -0
  27. data/app/views/containers/steps/preliminary.html.erb +18 -0
  28. data/config/routes.rb +5 -0
  29. data/db/migrate/20140930175337_add_email_to_compute_resource.rb +5 -0
  30. data/db/migrate/20141005233312_create_containers.rb +11 -0
  31. data/db/migrate/20141007225130_add_compute_resource_id_to_container.rb +5 -0
  32. data/db/migrate/20141009001613_add_tag_to_container.rb +5 -0
  33. data/db/migrate/20141009011026_add_attributes_to_container.rb +12 -0
  34. data/db/migrate/20141010173220_create_docker_images.rb +36 -0
  35. data/db/migrate/20141018110810_add_uuid_to_containers.rb +6 -0
  36. data/lib/foreman_docker/engine.rb +38 -6
  37. data/lib/foreman_docker/tasks/test.rake +44 -0
  38. data/lib/foreman_docker/version.rb +1 -1
  39. data/test/factories/compute_resources.rb +15 -0
  40. data/test/factories/containers.rb +6 -0
  41. data/test/factories/docker_image.rb +5 -0
  42. data/test/factories/docker_tag.rb +6 -0
  43. data/test/functionals/container_controller_test.rb +27 -0
  44. data/test/functionals/containers_steps_controller_test.rb +39 -0
  45. data/test/models/container_test.rb +36 -0
  46. data/test/models/docker_image_test.rb +12 -0
  47. data/test/models/docker_tag_test.rb +17 -0
  48. data/test/test_plugin_helper.rb +14 -0
  49. metadata +95 -85
  50. data/lib/tasks/foreman_docker_tasks.rake +0 -4
  51. data/test/dummy/README.rdoc +0 -28
  52. data/test/dummy/Rakefile +0 -6
  53. data/test/dummy/app/assets/javascripts/application.js +0 -13
  54. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  55. data/test/dummy/app/controllers/application_controller.rb +0 -5
  56. data/test/dummy/app/helpers/application_helper.rb +0 -2
  57. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  58. data/test/dummy/bin/bundle +0 -3
  59. data/test/dummy/bin/rails +0 -4
  60. data/test/dummy/bin/rake +0 -4
  61. data/test/dummy/config.ru +0 -4
  62. data/test/dummy/config/application.rb +0 -23
  63. data/test/dummy/config/boot.rb +0 -5
  64. data/test/dummy/config/database.yml +0 -25
  65. data/test/dummy/config/environment.rb +0 -5
  66. data/test/dummy/config/environments/development.rb +0 -29
  67. data/test/dummy/config/environments/production.rb +0 -80
  68. data/test/dummy/config/environments/test.rb +0 -36
  69. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  70. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  71. data/test/dummy/config/initializers/inflections.rb +0 -16
  72. data/test/dummy/config/initializers/mime_types.rb +0 -5
  73. data/test/dummy/config/initializers/secret_token.rb +0 -12
  74. data/test/dummy/config/initializers/session_store.rb +0 -3
  75. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  76. data/test/dummy/config/locales/en.yml +0 -23
  77. data/test/dummy/config/routes.rb +0 -56
  78. data/test/dummy/public/404.html +0 -58
  79. data/test/dummy/public/422.html +0 -58
  80. data/test/dummy/public/500.html +0 -57
  81. data/test/dummy/public/favicon.ico +0 -0
  82. data/test/foreman_docker_test.rb +0 -7
  83. data/test/test_helper.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2eb649de5602373b55a8f2647f5316df3d71e780
4
- data.tar.gz: f4e3932fa65ab2b2a557a08f770dd968b9fe7a80
3
+ metadata.gz: 11781ae40d79526d1ce98c52dddbb9341c9aa211
4
+ data.tar.gz: 87df5bd21364b87d937dda8d3de05cf9bae0b303
5
5
  SHA512:
6
- metadata.gz: aa8ce159e649b5ef010e426261e10dfee7ef27e2f28f095918747f31082828a305e3d8a26eff32e7254c996dc3627422364ae6df5ef3a41d624ae3f6b08b08c8
7
- data.tar.gz: 38d3229d713c16058c462922b5a2d3f744afad3fee0e7fbcef469da7cc5a1bbaadfffc9508f20207392e441056fc3f19d64e0a949b0526e705d08c7fa8358b0d
6
+ metadata.gz: 0c70da7838dc58dc17fb4e9bbd716fe0d3d34d3bba529923ad5d62968db33f58331760fd662806cb123df7922409e19009a5f8ddaeed51a12d9991db10d8eeeb
7
+ data.tar.gz: 5cde392c952ca19d530f17a8cac8e92ecb89f612143cce0d445ebe2e87e06b88895a25e28fd69025723e80a4f4c56bdd0af63822bb8c3bf0c999832aaa5abd09
data/README.md CHANGED
@@ -10,17 +10,23 @@ Please see the Foreman manual for appropriate instructions:
10
10
 
11
11
  The gem name is "foreman_docker".
12
12
 
13
+ RPM users can install the "ruby193-rubygem-foreman_docker" or "rubygem-foreman_docker" packages.
14
+
13
15
  ## Compatibility
14
16
 
15
17
  | Foreman Version | Plugin Version |
16
18
  | ---------------:| --------------:|
17
- | > 1.4 | 0.0.1 |
19
+ | >= 1.5 | 0.0.1 |
20
+
21
+ ## Testing
22
+
23
+ Run `rake test:docker:test` from your Foreman directory to run the test suite.
18
24
 
19
25
  ## Latest code
20
26
 
21
27
  You can get the develop branch of the plugin by specifying your Gemfile in this way:
22
28
 
23
- gem 'foreman_docker', :git => "https://github.com/abenari/foreman_docker.git"
29
+ gem 'foreman_docker', :git => "https://github.com/theforeman/foreman-docker.git"
24
30
 
25
31
  # Copyright
26
32
 
data/Rakefile CHANGED
@@ -1,7 +1,18 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
 
3
3
  begin
4
4
  require 'bundler/setup'
5
5
  rescue LoadError
6
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ Rails.logger.error 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ begin
10
+ require 'rubocop/rake_task'
11
+ RuboCop::RakeTask.new
12
+ rescue => _
13
+ puts "Rubocop not loaded."
14
+ end
15
+
16
+ task :default do
17
+ Rake::Task['rubocop'].execute
7
18
  end
@@ -0,0 +1,85 @@
1
+ .terminal {
2
+ .terminal-output .format {
3
+ display: inline-block;
4
+ }
5
+ .terminal-output div div {
6
+ display: inline-block;
7
+ }
8
+ .clipboard {
9
+ position: absolute;
10
+ bottom: 0;
11
+ left: 0;
12
+ opacity: 0.01;
13
+ filter: alpha(opacity = 0.01);
14
+ filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.01);
15
+ width: 2px;
16
+ }
17
+ }
18
+
19
+ .terminal {
20
+ padding: 10px;
21
+ position: relative;
22
+ overflow-y: scroll ;
23
+ }
24
+
25
+ .terminal {
26
+ .terminal-output div div {
27
+ display: block;
28
+ line-height: 14px;
29
+ height: auto;
30
+ }
31
+ .prompt {
32
+ display: block;
33
+ line-height: 14px;
34
+ height: auto;
35
+ float: left;
36
+ }
37
+ font-family: FreeMono,monospace;
38
+ color: rgba(255, 255, 255, 1);
39
+ background-color: rgba(47, 47, 47, 1);
40
+ font-size: 12px;
41
+ line-height: 14px;
42
+ }
43
+
44
+ .terminal-output > div {
45
+ min-height: 14px;
46
+ }
47
+
48
+ .terminal {
49
+ .terminal-output div span {
50
+ display: inline-block;
51
+ }
52
+ .terminal-output div {
53
+ div::-moz-selection, span::-moz-selection {
54
+ color: rgba(255, 255, 255, 1);
55
+ background-color: rgba(47, 47, 47, 1);
56
+ }
57
+ div {
58
+ a::-moz-selection, &::selection, a::selection {
59
+ color: rgba(255, 255, 255, 1);
60
+ background-color: rgba(47, 47, 47, 1);
61
+ }
62
+ }
63
+ span::selection {
64
+ color: rgba(255, 255, 255, 1);
65
+ background-color: rgba(47, 47, 47, 1);
66
+ }
67
+ }
68
+ .terminal-output div.error {
69
+ color: red;
70
+ div {
71
+ color: red;
72
+ }
73
+ }
74
+ }
75
+
76
+ .clear {
77
+ clear: both;
78
+ }
79
+
80
+ .terminal a {
81
+ color: #0F60FF;
82
+ &:hover {
83
+ color: red;
84
+ }
85
+ }
@@ -0,0 +1,55 @@
1
+ module Containers
2
+ class StepsController < ::ApplicationController
3
+ include Wicked::Wizard
4
+
5
+ steps :preliminary, :image, :configuration, :environment
6
+ before_filter :find_container
7
+
8
+ def show
9
+ case step
10
+ when :preliminary
11
+ @container_resources = ComputeResource.select { |cr| cr.provider == 'Docker' }
12
+ when :image
13
+ when :configuration
14
+ when :environment
15
+ end
16
+ render_wizard
17
+ end
18
+
19
+ def update
20
+ case step
21
+ when :preliminary
22
+ @container.update_attribute(:compute_resource_id, params[:container][:compute_resource_id])
23
+ when :image
24
+ @container.image = params[:image]
25
+ @container.update_attributes(params[:container])
26
+ when :configuration
27
+ @container.update_attributes(params[:container])
28
+ when :environment
29
+ @container.update_attributes(params[:container])
30
+ @container.uuid = start_container.id
31
+ end
32
+ render_wizard @container
33
+ end
34
+
35
+ private
36
+
37
+ def finish_wizard_path
38
+ container_path(:id => params[:container_id])
39
+ end
40
+
41
+ def allowed_resources
42
+ ComputeResource.authorized(:view_compute_resources)
43
+ end
44
+
45
+ def find_container
46
+ @container = Container.find(params[:container_id])
47
+ rescue ActiveRecord::RecordNotFound
48
+ not_found
49
+ end
50
+
51
+ def start_container
52
+ @container.compute_resource.create_vm(@container.parametrize)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,62 @@
1
+ class ContainersController < ::ApplicationController
2
+ before_filter :find_resource, :only => [:show]
3
+
4
+ def index
5
+ @container_resources = allowed_resources.select { |cr| cr.provider == 'Docker' }
6
+ if @container_resources.empty?
7
+ warning('You need a Compute Resource of type Docker to start managing containers')
8
+ redirect_to new_compute_resource_path
9
+ end
10
+ # This should only rescue Fog::Errors, but Fog returns all kinds of errors...
11
+ rescue
12
+ process_error
13
+ end
14
+
15
+ def new
16
+ @container = Container.create
17
+ redirect_to container_step_path(:container_id => @container.id, :id => :preliminary)
18
+ end
19
+
20
+ def destroy
21
+ if resource_deletion
22
+ process_success(:success_redirect => containers_path,
23
+ :success_msg => _("Container #{@deleted_identifier} is being deleted."))
24
+ else
25
+ process_error(:redirect => containers_path)
26
+ end
27
+ rescue ActiveRecord::RecordNotFound
28
+ not_found
29
+ end
30
+
31
+ def show
32
+ end
33
+
34
+ private
35
+
36
+ def resource_deletion
37
+ # Unmanaged container - only present in Compute Resource
38
+ if params[:compute_resource_id].present?
39
+ @deleted_identifier = params[:id]
40
+ destroy_compute_resource_vm(params[:compute_resource_id], params[:id])
41
+ else # Managed container
42
+ find_resource
43
+ @deleted_identifier = @container.name
44
+
45
+ destroy_compute_resource_vm(@container.compute_resource, @container.uuid) &&
46
+ @container.destroy
47
+ end
48
+ end
49
+
50
+ def destroy_compute_resource_vm(resource_id, uuid)
51
+ @container_resource = ComputeResource.authorized(:destroy_compute_resources_vms)
52
+ .find(resource_id)
53
+ @container_resource.destroy_vm(uuid)
54
+ rescue => error
55
+ logger.error "#{error.message} (#{error.class})\n#{error.backtrace.join("\n")}"
56
+ false
57
+ end
58
+
59
+ def allowed_resources
60
+ ComputeResource.authorized(:view_compute_resources)
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ module ContainerStepsHelper
2
+ def container_wizard(step)
3
+ wizard_header(
4
+ step,
5
+ _('Resource'),
6
+ _('Image'),
7
+ _('Configuration'),
8
+ _('Environment')
9
+ )
10
+ end
11
+ end
@@ -0,0 +1,54 @@
1
+ module ContainersHelper
2
+ def managed_icon(container, resource)
3
+ if managed?(container, resource)
4
+ '<span class="glyphicon glyphicon-check"></span>'.html_safe
5
+ else
6
+ '<span class="glyphicon glyphicon-unchecked"></span>'.html_safe
7
+ end
8
+ end
9
+
10
+ def managed?(container, resource)
11
+ uuids_in_resource(resource).include? container.identity
12
+ end
13
+
14
+ def uuids_in_resource(resource)
15
+ Container.where(:compute_resource_id => resource.id).pluck(:uuid)
16
+ end
17
+
18
+ def link_to_container(container, resource)
19
+ link_to_if_authorized container.name[1..-1].titleize,
20
+ container_link_hash(container, resource)
21
+ end
22
+
23
+ def container_link_hash(container, resource)
24
+ if managed?(container, resource)
25
+ hash_for_container_path(:id => Container.find_by_uuid(container.identity).id)
26
+ else
27
+ hash_for_compute_resource_vm_path(:compute_resource_id => resource,
28
+ :id => container.identity)
29
+ end
30
+ end
31
+
32
+ def container_title_actions(container)
33
+ @compute_resource = container.compute_resource
34
+ title_actions(
35
+ button_group(
36
+ link_to_if_authorized(_("Commit"), hash_for_container_path(:id => container)
37
+ .merge(:auth_object => container,
38
+ :permission => 'commit_containers'),
39
+ :title => _('Saves differences between image' \
40
+ 'and current state of container' \
41
+ 'as a new image'))
42
+ ),
43
+ button_group(vm_power_action(container.in_fog)),
44
+ button_group(
45
+ display_delete_if_authorized(
46
+ hash_for_container_path(:id => container.id)
47
+ .merge(:auth_object => container,
48
+ :auth_action => 'destroy',
49
+ :authorizer => authorizer),
50
+ :confirm => _("Delete %s?") % container.name)
51
+ )
52
+ )
53
+ end
54
+ end
@@ -8,7 +8,6 @@ module FogExtensions
8
8
  def name
9
9
  repo_tags.empty? ? (repository || id) : repo_tags.first
10
10
  end
11
-
12
11
  end
13
12
  end
14
- end
13
+ end
@@ -6,18 +6,28 @@ module FogExtensions
6
6
  include ActionView::Helpers::NumberHelper
7
7
 
8
8
  def state
9
- state_running ? "Running" :"Stopped"
9
+ state_running ? 'Running' : 'Stopped'
10
+ end
11
+
12
+ # Last time a container was started
13
+ # WARNING: this doesn't mean the container has been running since then.
14
+ def started_at
15
+ attributes['state_started_at']
16
+ end
17
+
18
+ def image_friendly_name
19
+ attributes['config_image']
10
20
  end
11
21
 
12
22
  def command
13
- c=[]
14
- c += entrypoint if entrypoint.any?
15
- c += cmd if cmd.any?
23
+ c = []
24
+ c += entrypoint if entrypoint.present?
25
+ c += cmd if cmd.present?
16
26
  c.join(' ')
17
27
  end
18
28
 
19
29
  def poweroff
20
- service.vm_action(:id =>id, :action => :kill)
30
+ service.vm_action(:id => id, :action => :kill)
21
31
  end
22
32
 
23
33
  def reset
@@ -26,9 +36,9 @@ module FogExtensions
26
36
  end
27
37
 
28
38
  def vm_description
29
- _("%{cores} Cores and %{memory} memory") % {:cores => cpus, :memory => number_to_human_size(memory.to_i)}
39
+ _('%{cores} Cores and %{memory} memory') %
40
+ { :cores => cpus, :memory => number_to_human_size(memory.to_i) }
30
41
  end
31
-
32
42
  end
33
43
  end
34
- end
44
+ end
@@ -0,0 +1,29 @@
1
+ class Container < ActiveRecord::Base
2
+ belongs_to :compute_resource
3
+ belongs_to :image, :class_name => 'DockerImage', :foreign_key => 'docker_image_id'
4
+ belongs_to :tag, :class_name => 'DockerTag', :foreign_key => 'docker_tag_id'
5
+
6
+ attr_accessible :command, :image, :name, :compute_resource_id, :entrypoint,
7
+ :cpu_set, :cpu_shares, :memory, :tty, :attach_stdin,
8
+ :attach_stdout, :attach_stderr, :tag, :uuid
9
+
10
+ def parametrize
11
+ { :name => name, :image => tag.tag.blank? ? image.image_id : "#{image.image_id}:#{tag.tag}",
12
+ :tty => tty, :memory => memory, :cmd => command.nil? ? '' : command.split(','),
13
+ :attach_stdout => attach_stdout, :attach_stdout => attach_stdout,
14
+ :attach_stderr => attach_stderr, :cpushares => cpu_shares, :cpuset => cpu_set }
15
+ end
16
+
17
+ def image=(image_id)
18
+ self[:docker_image_id] = DockerImage.find_or_create_by_image_id!(image_id).id
19
+ end
20
+
21
+ def tag=(tag_name)
22
+ self[:docker_tag_id] = DockerTag
23
+ .find_or_create_by_tag_and_docker_image_id!(tag_name, image.id).id
24
+ end
25
+
26
+ def in_fog
27
+ @fog_container ||= compute_resource.vms.get(uuid)
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ class DockerImage < ActiveRecord::Base
2
+ has_many :tags, :class_name => 'DockerTag', :foreign_key => 'docker_image_id',
3
+ :dependent => :destroy
4
+ has_many :containers
5
+
6
+ attr_accessible :image_id, :size
7
+ end
@@ -0,0 +1,7 @@
1
+ class DockerTag < ActiveRecord::Base
2
+ belongs_to :image, :class_name => 'DockerImage', :foreign_key => 'docker_image_id'
3
+
4
+ attr_accessible :tag, :image
5
+
6
+ validates :image, :presence => true
7
+ end
@@ -2,7 +2,6 @@ require 'uri'
2
2
 
3
3
  module ForemanDocker
4
4
  class Docker < ::ComputeResource
5
-
6
5
  validates :url, :format => { :with => URI.regexp }
7
6
 
8
7
  def self.model_name
@@ -18,16 +17,16 @@ module ForemanDocker
18
17
  end
19
18
 
20
19
  def provided_attributes
21
- super.merge({:mac => :mac})
20
+ super.merge(:mac => :mac)
22
21
  end
23
22
 
24
- #FIXME
23
+ # FIXME
25
24
  def max_cpu_count
26
25
  8
27
26
  end
28
27
 
29
28
  def max_memory
30
- 16*1024*1024*1024
29
+ 16 * 1024 * 1024 * 1024
31
30
  end
32
31
 
33
32
  def available_images
@@ -35,26 +34,34 @@ module ForemanDocker
35
34
  end
36
35
 
37
36
  def image(id)
38
- client.image.get(id) || raise(ActiveRecord::RecordNotFound)
37
+ client.image.get(id) || fail(ActiveRecord::RecordNotFound)
39
38
  end
40
39
 
41
40
  def provider_friendly_name
42
- "Docker"
41
+ 'Docker'
43
42
  end
44
43
 
45
- def create_vm args = {}
46
- args['cmd'] = Array.wrap( args.delete('cmd') )
44
+ def create_vm(args = {})
47
45
  options = vm_instance_defaults.merge(args)
48
46
  logger.debug("creating Docker with the following options: #{options.inspect}")
49
47
  client.servers.create options
50
- rescue Fog::Errors::Error => e
48
+ rescue Excon::Errors::SocketError, Fog::Errors::Error => e
51
49
  logger.debug "Fog error: #{e.message}\n " + e.backtrace.join("\n ")
52
50
  errors.add(:base, e.message.to_s)
53
51
  false
54
52
  end
55
53
 
56
54
  def vm_instance_defaults
57
- ActiveSupport::HashWithIndifferentAccess.new('name' => "foreman_#{Time.now.to_i}", 'cmd' => ['/bin/bash'])
55
+ ActiveSupport::HashWithIndifferentAccess.new('name' => "foreman_#{Time.now.to_i}",
56
+ 'cmd' => ['/bin/bash'])
57
+ end
58
+
59
+ def test_connection(options = {})
60
+ super
61
+ client
62
+ # This should only rescue Fog::Errors, but Fog returns all kinds of errors...
63
+ rescue => e
64
+ errors[:base] << e.message
58
65
  end
59
66
 
60
67
  protected
@@ -66,19 +73,18 @@ module ForemanDocker
66
73
  false
67
74
  end
68
75
 
69
-
70
76
  def client
71
77
  @client ||= ::Fog::Compute.new(
72
- :provider => "fogdocker",
73
- :docker_username => user,
74
- :docker_password => password,
75
- :docker_url => url
78
+ :provider => 'fogdocker',
79
+ :docker_username => user,
80
+ :docker_password => password,
81
+ :docker_email => email,
82
+ :docker_url => url
76
83
  )
77
84
  end
78
85
 
79
86
  def api_version
80
87
  @api_version ||= client.send(:client).api_version
81
88
  end
82
-
83
89
  end
84
90
  end