machinery-tool 1.0.2
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.
- checksums.yaml +7 -0
- data/COPYING +674 -0
- data/NEWS +143 -0
- data/bin/machinery +29 -0
- data/helpers/changed_managed_files.sh +32 -0
- data/helpers/filter-packages-for-build.yaml +6 -0
- data/html/assets/arrow_down.png +0 -0
- data/html/assets/arrow_up.png +0 -0
- data/html/assets/bootstrap-popover.js +113 -0
- data/html/assets/bootstrap-tooltip.js +457 -0
- data/html/assets/bootstrap.min.css +5 -0
- data/html/assets/collapse.js +174 -0
- data/html/assets/hogan-3.0.2.min.mustache.js +5 -0
- data/html/assets/jquery-2.1.1.min.js +4 -0
- data/html/assets/logo-changed-managed-files-small.png +0 -0
- data/html/assets/logo-changed-managed-files.png +0 -0
- data/html/assets/logo-config-files-small.png +0 -0
- data/html/assets/logo-config-files.png +0 -0
- data/html/assets/logo-groups-small.png +0 -0
- data/html/assets/logo-groups.png +0 -0
- data/html/assets/logo-os-small.png +0 -0
- data/html/assets/logo-os.png +0 -0
- data/html/assets/logo-packages-small.png +0 -0
- data/html/assets/logo-packages.png +0 -0
- data/html/assets/logo-patterns-small.png +0 -0
- data/html/assets/logo-patterns.png +0 -0
- data/html/assets/logo-repositories-small.png +0 -0
- data/html/assets/logo-repositories.png +0 -0
- data/html/assets/logo-services-small.png +0 -0
- data/html/assets/logo-services.png +0 -0
- data/html/assets/logo-unmanaged-files-small.png +0 -0
- data/html/assets/logo-unmanaged-files.png +0 -0
- data/html/assets/logo-users-small.png +0 -0
- data/html/assets/logo-users.png +0 -0
- data/html/assets/machinery-base.css +5767 -0
- data/html/assets/machinery.css +131 -0
- data/html/assets/machinery.js +148 -0
- data/html/assets/transition.js +59 -0
- data/html/assets/wheels_horizontal.png +0 -0
- data/html/index.html.haml +468 -0
- data/kiwi_helpers/kiwi_export_readme.md +22 -0
- data/kiwi_helpers/merge_users_and_groups.pl.erb +231 -0
- data/kiwi_helpers/unmanaged_files_build_excludes +5 -0
- data/lib/analyze_config_file_diffs_task.rb +130 -0
- data/lib/array.rb +98 -0
- data/lib/build_task.rb +124 -0
- data/lib/changed_rpm_files_helper.rb +96 -0
- data/lib/cli.rb +600 -0
- data/lib/compare_task.rb +68 -0
- data/lib/config.rb +33 -0
- data/lib/config_base.rb +117 -0
- data/lib/config_task.rb +56 -0
- data/lib/constants.rb +24 -0
- data/lib/copy_task.rb +22 -0
- data/lib/current_user.rb +23 -0
- data/lib/deploy_task.rb +89 -0
- data/lib/exceptions.rb +113 -0
- data/lib/generate_html_task.rb +22 -0
- data/lib/helper.rb +22 -0
- data/lib/hint.rb +39 -0
- data/lib/html.rb +103 -0
- data/lib/inspect_task.rb +93 -0
- data/lib/inspector.rb +65 -0
- data/lib/kiwi_config.rb +356 -0
- data/lib/kiwi_export_task.rb +36 -0
- data/lib/list_task.rb +64 -0
- data/lib/local_system.rb +127 -0
- data/lib/logged_cheetah.rb +25 -0
- data/lib/machinery.rb +85 -0
- data/lib/machinery_logger.rb +47 -0
- data/lib/migration.rb +128 -0
- data/lib/mountpoints.rb +72 -0
- data/lib/object.rb +138 -0
- data/lib/os.rb +78 -0
- data/lib/remote_system.rb +114 -0
- data/lib/remove_task.rb +43 -0
- data/lib/renderer.rb +243 -0
- data/lib/renderer_helper.rb +26 -0
- data/lib/rpm.rb +52 -0
- data/lib/scope_mixin.rb +38 -0
- data/lib/show_task.rb +65 -0
- data/lib/system.rb +81 -0
- data/lib/system_description.rb +228 -0
- data/lib/system_description_store.rb +167 -0
- data/lib/system_description_validator.rb +216 -0
- data/lib/tarball.rb +82 -0
- data/lib/ui.rb +74 -0
- data/lib/upgrade_format_task.rb +55 -0
- data/lib/validate_task.rb +23 -0
- data/lib/version.rb +22 -0
- data/lib/zypper.rb +70 -0
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +1056 -0
- data/plugins/docs/changed_managed_files.md +2 -0
- data/plugins/docs/config_files.md +5 -0
- data/plugins/docs/groups.md +2 -0
- data/plugins/docs/os.md +2 -0
- data/plugins/docs/packages.md +2 -0
- data/plugins/docs/patterns.md +5 -0
- data/plugins/docs/repositories.md +24 -0
- data/plugins/docs/services.md +6 -0
- data/plugins/docs/unmanaged_files.md +13 -0
- data/plugins/docs/users.md +3 -0
- data/plugins/inspect/changed_managed_files_inspector.rb +109 -0
- data/plugins/inspect/config_files_inspector.rb +117 -0
- data/plugins/inspect/groups_inspector.rb +46 -0
- data/plugins/inspect/os_inspector.rb +116 -0
- data/plugins/inspect/packages_inspector.rb +46 -0
- data/plugins/inspect/patterns_inspector.rb +67 -0
- data/plugins/inspect/repositories_inspector.rb +107 -0
- data/plugins/inspect/services_inspector.rb +88 -0
- data/plugins/inspect/unmanaged_files_inspector.rb +393 -0
- data/plugins/inspect/users_inspector.rb +87 -0
- data/plugins/model/changed_managed_files_model.rb +29 -0
- data/plugins/model/config_files_model.rb +29 -0
- data/plugins/model/groups_model.rb +26 -0
- data/plugins/model/os_model.rb +20 -0
- data/plugins/model/packages_model.rb +26 -0
- data/plugins/model/patterns_model.rb +26 -0
- data/plugins/model/repositories_model.rb +26 -0
- data/plugins/model/services_model.rb +48 -0
- data/plugins/model/unmanaged_files_model.rb +29 -0
- data/plugins/model/users_model.rb +26 -0
- data/plugins/schema/v1/system-description-changed-managed-files.schema.json +83 -0
- data/plugins/schema/v1/system-description-config-files.schema.json +83 -0
- data/plugins/schema/v1/system-description-groups.schema.json +30 -0
- data/plugins/schema/v1/system-description-os.schema.json +21 -0
- data/plugins/schema/v1/system-description-packages.schema.json +34 -0
- data/plugins/schema/v1/system-description-patterns.schema.json +24 -0
- data/plugins/schema/v1/system-description-repositories.schema.json +41 -0
- data/plugins/schema/v1/system-description-services.schema.json +30 -0
- data/plugins/schema/v1/system-description-unmanaged-files.schema.json +105 -0
- data/plugins/schema/v1/system-description-users.schema.json +61 -0
- data/plugins/schema/v2/system-description-changed-managed-files.schema.json +92 -0
- data/plugins/schema/v2/system-description-config-files.schema.json +92 -0
- data/plugins/schema/v2/system-description-groups.schema.json +30 -0
- data/plugins/schema/v2/system-description-os.schema.json +21 -0
- data/plugins/schema/v2/system-description-packages.schema.json +34 -0
- data/plugins/schema/v2/system-description-patterns.schema.json +24 -0
- data/plugins/schema/v2/system-description-repositories.schema.json +41 -0
- data/plugins/schema/v2/system-description-services.schema.json +30 -0
- data/plugins/schema/v2/system-description-unmanaged-files.schema.json +138 -0
- data/plugins/schema/v2/system-description-users.schema.json +61 -0
- data/plugins/show/changed_managed_files_renderer.rb +46 -0
- data/plugins/show/config_files_renderer.rb +62 -0
- data/plugins/show/groups_renderer.rb +36 -0
- data/plugins/show/os_renderer.rb +31 -0
- data/plugins/show/packages_renderer.rb +32 -0
- data/plugins/show/patterns_renderer.rb +32 -0
- data/plugins/show/repositories_renderer.rb +38 -0
- data/plugins/show/services_renderer.rb +32 -0
- data/plugins/show/unmanaged_files_renderer.rb +42 -0
- data/plugins/show/users_renderer.rb +35 -0
- data/schema/migrations/migrate1to2.rb +56 -0
- data/schema/v1/system-description-global.schema.json +31 -0
- data/schema/v2/system-description-global.schema.json +31 -0
- metadata +370 -0
data/lib/compare_task.rb
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
class CompareTask
|
|
19
|
+
def compare(description1, description2, scopes, options = {})
|
|
20
|
+
output = render_comparison(description1, description2, scopes, options)
|
|
21
|
+
|
|
22
|
+
Machinery::Ui.print_output(output, :no_pager => options[:no_pager])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def render_comparison(description1, description2, scopes, options = {})
|
|
26
|
+
output = ""
|
|
27
|
+
identical = true
|
|
28
|
+
common_scopes = false
|
|
29
|
+
scopes.each do |scope|
|
|
30
|
+
if description1[scope] && description2[scope]
|
|
31
|
+
comparison = description1[scope].compare_with(description2[scope])
|
|
32
|
+
|
|
33
|
+
partial_description1 = SystemDescription.new(
|
|
34
|
+
description1.name,
|
|
35
|
+
scope => comparison[0]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
partial_description2 = SystemDescription.new(
|
|
39
|
+
description2.name,
|
|
40
|
+
scope => comparison[1]
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
partial_description_common = SystemDescription.new("common", scope => comparison[2])
|
|
44
|
+
|
|
45
|
+
output += Renderer.for(scope).render_comparison(
|
|
46
|
+
partial_description1,
|
|
47
|
+
partial_description2,
|
|
48
|
+
partial_description_common,
|
|
49
|
+
options
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if partial_description1[scope] || partial_description2[scope]
|
|
53
|
+
identical = false
|
|
54
|
+
end
|
|
55
|
+
common_scopes = true
|
|
56
|
+
else
|
|
57
|
+
output += Renderer.for(scope).render_comparison_missing_scope(
|
|
58
|
+
description1, description2
|
|
59
|
+
)
|
|
60
|
+
identical = false if description1[scope] || description2[scope]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
output = "Compared descriptions are identical.\n" + output if identical && common_scopes
|
|
65
|
+
|
|
66
|
+
output
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/config.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# This file contains the defaults for machinery's configuration.
|
|
20
|
+
# They can be overwritten by the config file.
|
|
21
|
+
|
|
22
|
+
module Machinery
|
|
23
|
+
class Config < ConfigBase
|
|
24
|
+
def define_entries
|
|
25
|
+
default_config_file(Machinery::DEFAULT_CONFIG_FILE)
|
|
26
|
+
|
|
27
|
+
entry("hints",
|
|
28
|
+
default: true,
|
|
29
|
+
description: "Show hints about usage of Machinery in the context of the commands ran by the user"
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/config_base.rb
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# The defaults for machinery's configuration are defined in
|
|
20
|
+
# the file 'machinery_config.rb'.
|
|
21
|
+
|
|
22
|
+
class ConfigBase
|
|
23
|
+
def initialize
|
|
24
|
+
@entries = {}
|
|
25
|
+
@file = ""
|
|
26
|
+
define_entries
|
|
27
|
+
apply_custom_config(@file) if File.exist?(@file)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def default_config_file(file)
|
|
31
|
+
@file = file
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def entry(key, parameters = {})
|
|
35
|
+
@entries[key] = { value: parameters[:default], description: parameters[:description] }
|
|
36
|
+
create_method(key.to_sym) { get(key) }
|
|
37
|
+
create_method("#{key}=".to_sym) { |value| set(key, value) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def define_entries
|
|
41
|
+
raise NotImplementedError.new("No config entries defined for #{self.class}")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def each(&block)
|
|
45
|
+
@entries.each(&block)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def get(key)
|
|
49
|
+
ensure_config_exists(key)
|
|
50
|
+
@entries[key][:value]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def set(key, value, options = {auto_save: true} )
|
|
54
|
+
ensure_config_exists(key)
|
|
55
|
+
|
|
56
|
+
# Check if data type is correct. true and false are not of the same type which makes the check complex
|
|
57
|
+
if value.class != @entries[key][:value].class &&
|
|
58
|
+
! ( ( value == true || value == false ) && ( @entries[key][:value].class == TrueClass || @entries[key][:value].class == FalseClass ) )
|
|
59
|
+
raise Machinery::Errors::MachineryError.new("The value \"#{value}\" for configuration key \"#{key}\" is of an invalid data type.")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
@entries[key][:value] = value
|
|
63
|
+
|
|
64
|
+
save if options[:auto_save]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def save
|
|
71
|
+
config_table_stripped = {}
|
|
72
|
+
@entries.each do |key,value|
|
|
73
|
+
config_table_stripped[key] = value[:value]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
FileUtils.mkdir_p(Machinery::DEFAULT_CONFIG_DIR)
|
|
77
|
+
|
|
78
|
+
begin
|
|
79
|
+
File.write(@file, config_table_stripped.to_yaml)
|
|
80
|
+
Machinery.logger.info("Wrote configuration file \"#{@file}\".")
|
|
81
|
+
rescue => e
|
|
82
|
+
raise Machinery::Errors::MachineryError.new("Could not write configuration file \"#{@file}\": #{e}.")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def apply_custom_config(file)
|
|
87
|
+
content = read_config_file(file) || []
|
|
88
|
+
|
|
89
|
+
content.each do |key, value|
|
|
90
|
+
begin
|
|
91
|
+
set(key, value, :auto_save => false )
|
|
92
|
+
rescue => e
|
|
93
|
+
Machinery::Ui.warn "Warning: The machinery config file \"#{file}\" contains an invalid entry \"#{key}\":\n#{e}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def read_config_file(file)
|
|
99
|
+
begin
|
|
100
|
+
content = YAML.load_file(file)
|
|
101
|
+
Machinery.logger.info("Read configuration file \"#{file}\".")
|
|
102
|
+
rescue => e
|
|
103
|
+
Machinery::Ui.warn "Warning: Cannot parse machinery config file \"#{@file}\":\n#{e}"
|
|
104
|
+
end
|
|
105
|
+
content
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def ensure_config_exists(key)
|
|
109
|
+
if @entries[key].nil?
|
|
110
|
+
raise Machinery::Errors::UnknownConfig.new("Unknown configuration key: #{key}")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def create_method(name, &block)
|
|
115
|
+
self.class.send(:define_method, name, &block)
|
|
116
|
+
end
|
|
117
|
+
end
|
data/lib/config_task.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
class ConfigTask
|
|
19
|
+
def initialize(config = Machinery::Config.new)
|
|
20
|
+
@config = config
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def config(key = nil, value_string = nil)
|
|
24
|
+
if !key
|
|
25
|
+
# show all config entries
|
|
26
|
+
@config.each do |key, value|
|
|
27
|
+
Machinery::Ui.puts "#{key} = #{value[:value]} (#{value[:description]})"
|
|
28
|
+
end
|
|
29
|
+
elsif !value_string
|
|
30
|
+
# show one specific config entry
|
|
31
|
+
Machinery::Ui.puts "#{key} = #{@config.get(key)}"
|
|
32
|
+
else
|
|
33
|
+
# set one specific config entry
|
|
34
|
+
@config.set(key, parse_value_string(key, value_string))
|
|
35
|
+
Machinery::Ui.puts "#{key} = #{@config.get(key)}"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def parse_value_string(key, value_string)
|
|
40
|
+
current_value = @config.get(key)
|
|
41
|
+
|
|
42
|
+
if current_value == true || current_value == false
|
|
43
|
+
if value_string == "true" || value_string == "on"
|
|
44
|
+
return true
|
|
45
|
+
elsif value_string == "false" || value_string == "off"
|
|
46
|
+
return false
|
|
47
|
+
else
|
|
48
|
+
raise Machinery::Errors::MachineryError.new("The value '#{value_string}' is not valid for key '#{key}'.")
|
|
49
|
+
end
|
|
50
|
+
elsif current_value.kind_of?(Integer)
|
|
51
|
+
return value_string.to_i
|
|
52
|
+
else
|
|
53
|
+
return value_string
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/constants.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
module Machinery
|
|
19
|
+
ROOT = File.expand_path("..", File.dirname(__FILE__))
|
|
20
|
+
DEFAULT_CONFIG_DIR = File.join(ENV['HOME'], ".machinery")
|
|
21
|
+
DEFAULT_LOG_FILE = File.join(DEFAULT_CONFIG_DIR, "machinery.log")
|
|
22
|
+
DEFAULT_CONFIG_FILE = File.join(DEFAULT_CONFIG_DIR, "machinery.config")
|
|
23
|
+
IMAGE_META_DATA_FILE = "machinery.meta"
|
|
24
|
+
end
|
data/lib/copy_task.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
class CopyTask
|
|
19
|
+
def copy(store, from, to)
|
|
20
|
+
store.copy(from, to)
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/current_user.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
# Represents the user under which Machinery is running.
|
|
19
|
+
class CurrentUser
|
|
20
|
+
def is_root?
|
|
21
|
+
Process.euid == 0
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/deploy_task.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
class DeployTask
|
|
19
|
+
def deploy(description, cloud_config, options = {})
|
|
20
|
+
LocalSystem.validate_existence_of_package("python-glanceclient")
|
|
21
|
+
if !File.exists?(cloud_config)
|
|
22
|
+
raise(Machinery::Errors::DeployFailed,
|
|
23
|
+
"The cloud config file '#{cloud_config}' could not be found."
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if options[:image_dir]
|
|
28
|
+
if !Dir.exists?(options[:image_dir])
|
|
29
|
+
raise(Machinery::Errors::DeployFailed,
|
|
30
|
+
"The image directory does not exist."
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
image_dir = options[:image_dir]
|
|
34
|
+
else
|
|
35
|
+
image_dir = Dir.mktmpdir("#{description.name}-image", "/tmp")
|
|
36
|
+
is_temporary = true
|
|
37
|
+
task = BuildTask.new
|
|
38
|
+
task.build(description, image_dir)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
meta_data = load_meta_data(image_dir)
|
|
42
|
+
image_file = File.join(image_dir, meta_data[:image_file])
|
|
43
|
+
|
|
44
|
+
if meta_data[:description] != description.name
|
|
45
|
+
raise(Machinery::Errors::MissingRequirement,
|
|
46
|
+
"The image file '#{image_file}' was not build from the provided system description."
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if !File.exists?(image_file)
|
|
51
|
+
raise(Machinery::Errors::DeployFailed,
|
|
52
|
+
"The image file '#{image_file}' does not exist."
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
command = "/usr/bin/glance"
|
|
57
|
+
command << " --insecure" if options[:insecure]
|
|
58
|
+
command << " image-create"
|
|
59
|
+
command << " --name=#{options[:image_name] || description.name}"
|
|
60
|
+
command << " --disk-format=qcow2 --container-format=bare"
|
|
61
|
+
command << " --file=#{Shellwords.escape(image_file)}"
|
|
62
|
+
|
|
63
|
+
system "sh -c '. #{Shellwords.escape(cloud_config)} && #{command}'"
|
|
64
|
+
|
|
65
|
+
if is_temporary && image_dir.start_with?("/tmp/")
|
|
66
|
+
FileUtils.rm_rf(image_dir)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def load_meta_data(meta_dir)
|
|
73
|
+
meta_file = File.join(meta_dir, Machinery::IMAGE_META_DATA_FILE)
|
|
74
|
+
if !File.exists?(meta_file)
|
|
75
|
+
raise(Machinery::Errors::DeployFailed,
|
|
76
|
+
"The meta data file '#{meta_file}' could not be found."
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
meta_data = YAML.load_file(meta_file)
|
|
81
|
+
|
|
82
|
+
if !meta_data[:image_file] || !meta_data[:description]
|
|
83
|
+
raise(Machinery::Errors::DeployFailed,
|
|
84
|
+
"The meta data file '#{meta_file}' is broken."
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
meta_data
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/exceptions.rb
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
2
|
+
#
|
|
3
|
+
# This program is free software; you can redistribute it and/or
|
|
4
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
5
|
+
# published by the Free Software Foundation.
|
|
6
|
+
#
|
|
7
|
+
# This program is distributed in the hope that it will be useful,
|
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10
|
+
# GNU General Public License for more details.
|
|
11
|
+
#
|
|
12
|
+
# You should have received a copy of the GNU General Public License
|
|
13
|
+
# along with this program; if not, contact SUSE LLC.
|
|
14
|
+
#
|
|
15
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
16
|
+
# you may find current contact information at www.suse.com
|
|
17
|
+
|
|
18
|
+
module Machinery
|
|
19
|
+
module Errors
|
|
20
|
+
class IncompatibleHost < StandardError; end
|
|
21
|
+
|
|
22
|
+
# Superclass for all "expected" errors in Machinery.
|
|
23
|
+
# "Expected" errors are errors which are caused by the environment or input
|
|
24
|
+
# data and are not caused by bugs in the machinery codebase.
|
|
25
|
+
#
|
|
26
|
+
# Those errors will be handled specially by the machinery tool, e.g. by not
|
|
27
|
+
# showing a backtrace.
|
|
28
|
+
class MachineryError < StandardError; end
|
|
29
|
+
|
|
30
|
+
class UnknownScope < MachineryError; end
|
|
31
|
+
class UnknownOs < MachineryError; end
|
|
32
|
+
class InvalidPager < MachineryError; end
|
|
33
|
+
class InvalidCommandLine < MachineryError; end
|
|
34
|
+
|
|
35
|
+
class MissingRequirement < MachineryError; end
|
|
36
|
+
|
|
37
|
+
class SystemDescriptionError < MachineryError; end
|
|
38
|
+
class SystemDescriptionNotFound < SystemDescriptionError; end
|
|
39
|
+
|
|
40
|
+
class SystemDescriptionIncompatible < SystemDescriptionError
|
|
41
|
+
attr_reader :name
|
|
42
|
+
|
|
43
|
+
def initialize(name)
|
|
44
|
+
@name = name
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_s
|
|
48
|
+
"The system description '#{@name}' has an incompatible data " \
|
|
49
|
+
"format and can not be read.\n" \
|
|
50
|
+
"Try '#{$0} upgrade-format #{name}' to upgrade it to the current version.\n"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class MissingExtractedFiles < SystemDescriptionError
|
|
55
|
+
def initialize(description, scopes)
|
|
56
|
+
@description = description
|
|
57
|
+
@scopes = scopes
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_s
|
|
61
|
+
meta = @description[@scopes.first].meta
|
|
62
|
+
hostname = @scopes.map do |s|
|
|
63
|
+
@description[s].meta.hostname if @description[s].meta
|
|
64
|
+
end.compact.first || "<HOSTNAME>"
|
|
65
|
+
formatted_scopes = Machinery::Ui.internal_scope_list_to_string(@scopes)
|
|
66
|
+
|
|
67
|
+
cmd = "#{$0} inspect --extract-files --scope=#{formatted_scopes}"
|
|
68
|
+
cmd += " --name='#{@description.name}'" if hostname != @description.name
|
|
69
|
+
cmd += " #{hostname}"
|
|
70
|
+
|
|
71
|
+
if @scopes.count > 1
|
|
72
|
+
output = "The following scopes '#{formatted_scopes}' are part of the system description"
|
|
73
|
+
else
|
|
74
|
+
output = "The scope '#{formatted_scopes}' is part of the system description"
|
|
75
|
+
end
|
|
76
|
+
output += " but the corresponding files weren't extracted during inspection.\n" \
|
|
77
|
+
"The files are required to continue with this command." \
|
|
78
|
+
" Run `#{cmd}` to extract them."
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class SystemDescriptionValidationFailed < SystemDescriptionError
|
|
83
|
+
attr_reader :errors
|
|
84
|
+
attr_accessor :header
|
|
85
|
+
|
|
86
|
+
def initialize(errors)
|
|
87
|
+
@errors = errors
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def to_s
|
|
91
|
+
message = ""
|
|
92
|
+
if @header
|
|
93
|
+
message += header + "\n\n"
|
|
94
|
+
end
|
|
95
|
+
message += @errors.join("\n")
|
|
96
|
+
message += "\n"
|
|
97
|
+
message
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class MigrationError < MachineryError; end
|
|
102
|
+
|
|
103
|
+
class BuildFailed < MachineryError; end
|
|
104
|
+
class DeployFailed < MachineryError; end
|
|
105
|
+
class InspectionFailed < MachineryError; end
|
|
106
|
+
class KiwiExportFailed < MachineryError; end
|
|
107
|
+
|
|
108
|
+
class SshConnectionFailed < MachineryError; end
|
|
109
|
+
class RsyncFailed < MachineryError; end
|
|
110
|
+
class OpenInBrowserFailed < MachineryError; end
|
|
111
|
+
class UnknownConfig < MachineryError; end
|
|
112
|
+
end
|
|
113
|
+
end
|