foreman_xen 0.0.4.1 → 0.0.5

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.
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ # Development policy #
2
+
3
+ Currently we hold master branch as tested and verified version, please submit your changes into development branch only.
4
+
1
5
  # Foreman XEN Plugin
2
6
 
3
7
  This plugin enables provisioning and managing XEN Server in Foreman.
@@ -0,0 +1,176 @@
1
+ module ForemanXen
2
+ class SnapshotsController < ::ApplicationController
3
+ helper :all
4
+ skip_before_filter :verify_authenticity_token
5
+
6
+ #GET - foreman_xen/snapshots/:host_id
7
+ def show
8
+ id = params[:id]
9
+ if id != nil && id != ""
10
+ @host = get_host_by_id(id)
11
+ end
12
+ puts @host.inspect
13
+ if !@host.nil? && @host.compute_resource_id
14
+ @compute_resource = get_compute_resource_for_host(@host)
15
+ if !@compute_resource.nil?
16
+ vm = @compute_resource.find_vm_by_uuid(@host.uuid)
17
+ if !vm.nil?
18
+ @snapshots = @compute_resource.get_snapshots_for_vm(vm)
19
+ else
20
+ process_error({:error_msg => "Error retrieving compute resource #{@host.compute_resource_id} from provider."})
21
+ return
22
+ end
23
+ end
24
+ elsif @host.nil?
25
+ process_error({:error_msg => "No host found with ID: #{id}."})
26
+ return
27
+ else
28
+ process_error({:error_msg => "No compute resource found for host with ID: #{id}."})
29
+ return
30
+ end
31
+ end
32
+
33
+ #GET = foreman_xen/snapshots/revert
34
+ def revert
35
+ id = params[:id]
36
+ ref = params[:ref]
37
+ @host = get_host_by_id(id)
38
+ @compute_resource = get_compute_resource_by_host_id(id)
39
+ if @compute_resource
40
+ if @host
41
+ vm = @compute_resource.find_vm_by_uuid(@host.uuid)
42
+ vm.revert(ref)
43
+ vm.start
44
+ process_success({:success_msg => "Succesfully reverted and powered on #{@host.name}", :success_redirect => "/foreman_xen/snapshots/#{id}"})
45
+ return
46
+ else
47
+ process_error({:error_msg => "Error retrieving host information for #{@host.name}" })
48
+ return
49
+ end
50
+ else
51
+ process_error({:error_msg => "Error retrieving compute resource information for #{@host.name}" })
52
+ return
53
+ end
54
+ process_success({:success_msg => ("Succesfully reverted #{@host.name}"), :success_redirect => "/foreman_xen/snapshots/#{id}"})
55
+ return
56
+ end
57
+
58
+ #GET = foreman_xen/snapshots/delete
59
+ def destroy
60
+ ref = params[:ref]
61
+ id = params[:id]
62
+ @host = get_host_by_id(id)
63
+ @compute_resource = get_compute_resource_by_host_id(id)
64
+ name = nil
65
+ if @compute_resource
66
+ if @host
67
+ snapshots = @compute_resource.get_snapshots
68
+ snapshots.each do | snapshot |
69
+ if snapshot.reference == ref
70
+ name = snapshot.name
71
+ snapshot.destroy
72
+ notice ("Succesfully deleted snapshot #{snapshot.name}")
73
+ break
74
+ end
75
+ end
76
+ else
77
+ process_error({:error_msg => ("Error retrieving host information for host id: #{id}")})
78
+ return
79
+ end
80
+ else
81
+ process_error({:error_msg => ("Error retrieving compute resource information for host id: #{id}")})
82
+ return
83
+ end
84
+ process_success({:success_msg => ("Succesfully deleted snapshot: #{name}"), :success_redirect => "/foreman_xen/snapshots/#{id}"})
85
+ return
86
+ end
87
+
88
+ #GET = foreman_xen/snapshots/:id/new
89
+ def new
90
+ id = params[:id]
91
+ @host = get_host_by_id(id)
92
+ if !@host.nil?
93
+ @compute_resource = get_compute_resource_by_host_id(id)
94
+ if @compute_resource.nil?
95
+ process_error({:error_msg => "Error retrieving compute information for compute resource id: #{@host.compute_resource_id}"})
96
+ return
97
+ end
98
+ else
99
+ process_error({:error_msg => "Error retrieving host information for host id: #{id}"})
100
+ return
101
+ end
102
+ end
103
+
104
+ #POST = foreman_xen/snapshots/:id/create
105
+ def create
106
+ id = params[:id]
107
+ name = params[:name]
108
+ if name.nil? || name == ""
109
+ process_error({:error_msg => "You must supply a name."})
110
+ return
111
+ end
112
+ @host = get_host_by_id(id)
113
+ if !@host.nil?
114
+ @compute_resource = get_compute_resource_by_host_id(id)
115
+ else
116
+ process_error({:error_msg => "Error retrieving host information for host id #{id}"})
117
+ return
118
+ end
119
+ if !@compute_resource.nil?
120
+ vm = @compute_resource.find_vm_by_uuid(@host.uuid)
121
+ if !vm.nil?
122
+ vm.snapshot(name)
123
+ process_success({:success_msg => "Succesfully created snapshot #{name} for #{@host.name}", :success_redirect => "/foreman_xen/snapshots/#{id}"})
124
+ return
125
+ else
126
+ process_error({:error_msg => "Error retrieving compute resource information for #{@host.name}"})
127
+ return
128
+ end
129
+ else
130
+ process_error({:error_msg => "Error retrieving compute provider information for #{@host.name}"})
131
+ return
132
+ end
133
+ end
134
+
135
+ def snapshots_url
136
+ case params[:action]
137
+ when 'show'
138
+ return '/'
139
+ when 'new'
140
+ id = params[:id]
141
+ if id.nil?
142
+ return '/'
143
+ else
144
+ return "/foreman_xen/snapshots/#{id}"
145
+ end
146
+ when 'create'
147
+ id = params[:id]
148
+ if id.nil?
149
+ return '/'
150
+ else
151
+ return "/foreman_xen/snapshots/#{id}/new"
152
+ end
153
+ end
154
+ end
155
+
156
+ private
157
+
158
+ def get_host_by_id(host_id)
159
+ Host::Managed.where(:id => host_id).to_a[0]
160
+ end
161
+
162
+ def get_compute_resource_by_host_id(host_id)
163
+ host = get_host_by_id(host_id)
164
+ if host
165
+ ComputeResource.where(:id => host.compute_resource_id).to_a[0]
166
+ end
167
+ end
168
+
169
+ def get_compute_resource_for_host(host)
170
+ if host
171
+ ComputeResource.where(:id => host.compute_resource_id).to_a[0]
172
+ end
173
+ end
174
+
175
+ end
176
+ end
@@ -0,0 +1,78 @@
1
+ module ForemanXen
2
+ module HostHelperExtensions
3
+ extend ActiveSupport::Concern
4
+ def host_title_actions(host)
5
+ title_actions(
6
+ button_group(
7
+ link_to_if_authorized(_("Edit"), hash_for_edit_host_path(:id => host).merge(:auth_object => host),
8
+ :title => _("Edit your host")),
9
+ if host.build
10
+ link_to_if_authorized(_("Cancel build"), hash_for_cancelBuild_host_path(:id => host).merge(:auth_object => host, :permission => 'build_hosts'),
11
+ :disabled => host.can_be_built?,
12
+ :title => _("Cancel build request for this host"))
13
+ else
14
+ link_to_if_authorized(_("Build"), hash_for_setBuild_host_path(:id => host).merge(:auth_object => host, :permission => 'build_hosts'),
15
+ :disabled => !host.can_be_built?,
16
+ :title => _("Enable rebuild on next host boot"),
17
+ :confirm => _("Rebuild %s on next reboot?\nThis would also delete all of its current facts and reports") % host)
18
+ end
19
+ ),
20
+ if host.compute_resource_id || host.bmc_available?
21
+ button_group(
22
+ link_to(_("Loading power state ..."), '#', :disabled => true, :id => :loading_power_state)
23
+ )
24
+ end,
25
+ button_group(
26
+ if host.try(:puppet_proxy)
27
+ link_to_if_authorized(_("Run puppet"), hash_for_puppetrun_host_path(:id => host).merge(:auth_object => host, :permission => 'puppetrun_hosts'),
28
+ :disabled => !Setting[:puppetrun],
29
+ :title => _("Trigger a puppetrun on a node; requires that puppet run is enabled"))
30
+ end
31
+ ),
32
+ button_group(
33
+ link_to_if_authorized(_("Delete"), hash_for_host_path(:id => host).merge(:auth_object => host, :permission => 'destroy_hosts'),
34
+ :class => "btn btn-danger", :confirm => _('Are you sure?'), :method => :delete)
35
+ )
36
+ )
37
+ end
38
+
39
+ def xen_host_title_actions(host)
40
+ title_actions(
41
+ button_group(
42
+ link_to_if_authorized(_("Edit"), hash_for_edit_host_path(:id => host).merge(:auth_object => host),
43
+ :title => _("Edit your host")),
44
+ if host.compute_resource_id
45
+ link_to(_("Snapshots"), "../foreman_xen/snapshots/#{@host.id}/",
46
+ :title => _("Manage machine snapshots"))
47
+ end,
48
+ if host.build
49
+ link_to_if_authorized(_("Cancel build"), hash_for_cancelBuild_host_path(:id => host).merge(:auth_object => host, :permission => 'build_hosts'),
50
+ :disabled => host.can_be_built?,
51
+ :title => _("Cancel build request for this host"))
52
+ else
53
+ link_to_if_authorized(_("Build"), hash_for_setBuild_host_path(:id => host).merge(:auth_object => host, :permission => 'build_hosts'),
54
+ :disabled => !host.can_be_built?,
55
+ :title => _("Enable rebuild on next host boot"),
56
+ :confirm => _("Rebuild %s on next reboot?\nThis would also delete all of its current facts and reports") % host)
57
+ end
58
+ ),
59
+ if host.compute_resource_id || host.bmc_available?
60
+ button_group(
61
+ link_to(_("Loading power state ..."), '#', :disabled => true, :id => :loading_power_state)
62
+ )
63
+ end,
64
+ button_group(
65
+ if host.try(:puppet_proxy)
66
+ link_to_if_authorized(_("Run puppet"), hash_for_puppetrun_host_path(:id => host).merge(:auth_object => host, :permission => 'puppetrun_hosts'),
67
+ :disabled => !Setting[:puppetrun],
68
+ :title => _("Trigger a puppetrun on a node; requires that puppet run is enabled"))
69
+ end
70
+ ),
71
+ button_group(
72
+ link_to_if_authorized(_("Delete"), hash_for_host_path(:id => host).merge(:auth_object => host, :permission => 'destroy_hosts'),
73
+ :class => "btn btn-danger", :confirm => _('Are you sure?'), :method => :delete)
74
+ )
75
+ )
76
+ end
77
+ end
78
+ end
@@ -104,6 +104,23 @@ module ForemanXen
104
104
  Host.authorized(:view_hosts, Host).where(:ip => ips).first
105
105
  end
106
106
 
107
+ def get_snapshots_for_vm(vm)
108
+ if vm.snapshots.empty?
109
+ return []
110
+ end
111
+ tmps = client.servers.templates.select { |t| t.is_a_snapshot } rescue []
112
+ retval = []
113
+ tmps.each do | snapshot |
114
+ retval << snapshot if vm.snapshots.include?(snapshot.reference)
115
+ end
116
+ retval
117
+ end
118
+
119
+ def get_snapshots
120
+ tmps = client.servers.templates.select { |t| t.is_a_snapshot } rescue []
121
+ tmps.sort { |a, b| a.name <=> b.name }
122
+ end
123
+
107
124
  def new_vm(attr={})
108
125
 
109
126
  test_connection
@@ -0,0 +1,2 @@
1
+ <!-- replace 'erb[loud]:contains("host_title_actions")' -->
2
+ <%= xen_host_title_actions(@host) %>
@@ -0,0 +1,2 @@
1
+ <!-- replace 'code[erb-loud]:contains("host_title_actions")' -->
2
+ <%= xen_host_title_actions(@host) %>
@@ -0,0 +1,23 @@
1
+ <% title _("Create Snapshot") %>
2
+
3
+ <%= form_tag("create", method: "post") do %>
4
+ <div class="clearfix">
5
+ <div class="form-group">
6
+ <%= label_tag 'name', 'Name:', class: 'col-md-2 control-label' %>
7
+ <div class="col-md-8">
8
+ <%= text_field_tag(:name, nil, class: "form-control") %>
9
+ </div>
10
+
11
+ <div class="col-md-8">
12
+
13
+ </div>
14
+ </div>
15
+ </div>
16
+ <div class = "row form-group"></div>
17
+ <div class="clearfix">
18
+ <div class="form-actions">
19
+ <%= link_to("Cancel", "/foreman_xen/snapshots/#{@host.id}", :id => "cancel_button", :class => "btn btn-danger") %>
20
+ <%= submit_tag("Create", class: "btn btn-primary") %>
21
+ </div>
22
+ </div>
23
+ <% end %>
@@ -0,0 +1,25 @@
1
+ <% title _("Snapshots: #{@host.name}") %>
2
+ <%= title_actions(
3
+ button_group(link_to("Take Snapshot", "/foreman_xen/snapshots/#{@host.id}/new", :id => "takeSnapshotButton", :class => "btn btn-success"),
4
+ link_to_if_authorized(_("Back to host"), hash_for_host_path(:id => @host), :title => _("Back to host"), :class => 'btn btn-default')
5
+ ) ) %>
6
+
7
+ <table class="table table-hover">
8
+ <tbody>
9
+ <th>Name</th>
10
+ <th>Snapshot Time</th>
11
+ <th>Actions</th>
12
+ <% @snapshots.each do |snapshot| %>
13
+ <tr>
14
+ <td><%= h snapshot.name %></a></td>
15
+ <td><%= h "#{snapshot.snapshot_time.to_date} #{snapshot.snapshot_time.to_time} " %></a></td>
16
+ <td>
17
+ <div class="form-group">
18
+ <%= link_to("Revert", "/foreman_xen/snapshots/#{@host.id}/revert/#{snapshot.reference}", :id => "revertSnapshotButton", :class => "btn btn-danger", data: { confirm: "Confirm revert to #{snapshot.name}? Please note that all changes since the snapshot time will be lost, and the system will be restarted."})%>
19
+ <%= link_to("Delete", "/foreman_xen/snapshots/#{@host.id}/delete/#{snapshot.reference}", :id => "deleteSnapshotButton", :class => "btn btn-danger", data: { confirm: "Delete snapshot #{snapshot.name}?"})%>
20
+ </div>
21
+ </td>
22
+ </tr>
23
+ <% end %>
24
+ </tbody>
25
+ </table>
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ Rails.application.routes.draw do
2
+
3
+ namespace :foreman_xen do
4
+ match 'snapshots/:id', :to => 'snapshots#show', :via => 'get'
5
+ match 'snapshots/:id/revert/:ref', :to => 'snapshots#revert', :via => 'get'
6
+ match 'snapshots/:id/new', :to => 'snapshots#new', :via => 'get'
7
+ match 'snapshots/:id/delete/:ref', :to => 'snapshots#destroy', :via => 'get'
8
+
9
+ match 'snapshots/:id/create', :to => 'snapshots#create', :via => 'post'
10
+ end
11
+
12
+ end
@@ -1,6 +1,7 @@
1
1
  require 'fast_gettext'
2
2
  require 'gettext_i18n_rails'
3
3
  require 'fog'
4
+ require 'deface'
4
5
 
5
6
  module ForemanXen
6
7
  #Inherit from the Rails module of the parent app (Foreman), not the plugin.
@@ -23,10 +24,23 @@ module ForemanXen
23
24
 
24
25
  end
25
26
 
27
+ config.to_prepare do
28
+ begin
29
+ # extend fog xen server and image models.
30
+ require 'fog/xenserver/models/compute/server'
31
+ require File.expand_path('../../../app/models/concerns/fog_extensions/xenserver/server', __FILE__)
32
+ require File.expand_path('../../../app/models/concerns/foreman_xen/host_helper_extensions', __FILE__)
33
+
34
+ Fog::Compute::XenServer::Server.send(:include, ::FogExtensions::Xenserver::Server)
35
+ ::HostsHelper.send(:include, ForemanXen::HostHelperExtensions)
36
+ rescue => e
37
+ puts "Foreman-Xen: skipping engine hook (#{e.to_s})"
38
+ end
39
+ end
40
+
26
41
  end
27
42
 
28
- # extend fog xen server and image models.
29
- require 'fog/xenserver/models/compute/server'
30
- require File.expand_path('../../../app/models/concerns/fog_extensions/xenserver/server', __FILE__)
31
- Fog::Compute::XenServer::Server.send(:include, ::FogExtensions::Xenserver::Server)
43
+
44
+
45
+
32
46
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanXen
2
- VERSION = "0.0.4.1"
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,98 +1,126 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: foreman_xen
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.4.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 5
10
+ version: 0.0.5
5
11
  platform: ruby
6
- authors:
7
- - Pavel Nemirovsky, Michał Piotrowski, Avi Israeli
12
+ authors:
13
+ - "Pavel Nemirovsky, Micha\xC5\x82 Piotrowski, Avi Israeli"
8
14
  autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
- date: 2014-11-21 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2014-12-17 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
14
22
  name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
23
  prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
28
36
  name: fog
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
37
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
41
49
  description: Provision and manage XEN Server from Foreman.
42
- email:
50
+ email:
43
51
  - operations@oovoo.com
44
52
  executables: []
53
+
45
54
  extensions: []
55
+
46
56
  extra_rdoc_files: []
47
- files:
57
+
58
+ files:
59
+ - app/models/concerns/foreman_xen/host_helper_extensions.rb
60
+ - app/models/concerns/fog_extensions/xenserver/server.rb
61
+ - app/models/foreman_xen/xenserver.rb
48
62
  - app/views/compute_resources/show/_xenserver.html.erb
49
63
  - app/views/compute_resources/form/_xenserver.html.erb
50
- - app/views/api/v2/compute_resources/xenserver.json.rabl
51
64
  - app/views/api/v1/compute_resources/xenserver.json.rabl
65
+ - app/views/api/v2/compute_resources/xenserver.json.rabl
66
+ - app/views/foreman_xen/snapshots/show.html.erb
67
+ - app/views/foreman_xen/snapshots/new.html.erb
52
68
  - app/views/compute_resources_vms/show/_xenserver.html.erb
53
- - app/views/compute_resources_vms/form/_xenstore.html.erb
69
+ - app/views/compute_resources_vms/index/_xenserver.html.erb
54
70
  - app/views/compute_resources_vms/form/_volume.html.erb
71
+ - app/views/compute_resources_vms/form/_xenserver.html.erb
55
72
  - app/views/compute_resources_vms/form/_templates.html.erb
73
+ - app/views/compute_resources_vms/form/_xenstore.html.erb
56
74
  - app/views/compute_resources_vms/form/_network.html.erb
57
- - app/views/compute_resources_vms/form/_xenserver.html.erb
58
- - app/views/compute_resources_vms/index/_xenserver.html.erb
59
- - app/models/concerns/fog_extensions/xenserver/server.rb
60
- - app/models/foreman_xen/xenserver.rb
61
- - lib/foreman_xen.rb
75
+ - app/controllers/foreman_xen/snapshots_controller.rb
76
+ - app/overrides/hosts/show/snapshot_override_legacy.html.erb.deface
77
+ - app/overrides/hosts/show/snapshot_override.html.erb.deface
78
+ - config/routes.rb
79
+ - lib/tasks/foreman_xen_tasks.rake
80
+ - lib/foreman_xen/vnc_tunnel.rb
62
81
  - lib/foreman_xen/engine.rb
63
82
  - lib/foreman_xen/version.rb
64
- - lib/foreman_xen/vnc_tunnel.rb
65
- - lib/tasks/foreman_xen_tasks.rake
83
+ - lib/foreman_xen.rb
66
84
  - locale/Makefile
67
85
  - LICENSE
68
86
  - Rakefile
69
87
  - README.md
70
- - test/foreman_xen_test.rb
71
88
  - test/test_helper.rb
89
+ - test/foreman_xen_test.rb
90
+ has_rdoc: true
72
91
  homepage: http://github.com/theforeman/foreman-xen
73
- licenses:
92
+ licenses:
74
93
  - GPL-3
75
- metadata: {}
76
94
  post_install_message:
77
95
  rdoc_options: []
78
- require_paths:
96
+
97
+ require_paths:
79
98
  - lib
80
- required_ruby_version: !ruby/object:Gem::Requirement
81
- requirements:
82
- - - '>='
83
- - !ruby/object:Gem::Version
84
- version: '0'
85
- required_rubygems_version: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - '>='
88
- - !ruby/object:Gem::Version
89
- version: '0'
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
90
117
  requirements: []
118
+
91
119
  rubyforge_project:
92
- rubygems_version: 2.0.6
120
+ rubygems_version: 1.3.7
93
121
  signing_key:
94
- specification_version: 4
122
+ specification_version: 3
95
123
  summary: Provision and manage XEN Server from Foreman
96
- test_files:
97
- - test/foreman_xen_test.rb
124
+ test_files:
98
125
  - test/test_helper.rb
126
+ - test/foreman_xen_test.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: f37dcf6c9110e2acf87ef685d655b24890cbc920
4
- data.tar.gz: 1be46948238513d6e9c1f11ef016e156a2c8ec07
5
- SHA512:
6
- metadata.gz: 4e08405948fc85e6251932fd9a20e6d0e903fa3abe06af8ed7d3402dfa887cdaac0ac9d6c35996115492a194fe719a750927b6676e283925523d92f7f6a6aa0b
7
- data.tar.gz: d958ac6baba71844c0f219d571851206527640e20b92a4cc6475becb89865c5440f80470daf7f9b448b039909911b911be250c0a5f36903f475b9bfd402f68ec