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/mountpoints.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
# MountPoints represents the currently mounted file systems of the
|
|
19
|
+
# inspected system.
|
|
20
|
+
#
|
|
21
|
+
# all() returns an array containing the mount points of all mounted
|
|
22
|
+
# file systems
|
|
23
|
+
#
|
|
24
|
+
# remote() returns an array containing the mount points of all mounted
|
|
25
|
+
# file systems that are remote file systems (e.g. nfs, cifs)
|
|
26
|
+
#
|
|
27
|
+
# local() returns an array containing the mount points of all mounted
|
|
28
|
+
# local file systems with permanent data (e.g. ext3, btrfs, xfs)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MountPoints
|
|
32
|
+
attr_reader :mounts
|
|
33
|
+
REMOTE_FILE_SYSTEMS = ["autofs", "cifs", "nfs", "nfs4"]
|
|
34
|
+
LOCAL_FILE_SYSTEMS = ["ext2", "ext3", "ext4", "reiserfs", "btrfs", "vfat", "xfs", "jfs"]
|
|
35
|
+
def initialize(system)
|
|
36
|
+
@mounts = parse_mounts(system.read_file("/proc/mounts"))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def remote
|
|
40
|
+
@mounts.select { |fs_file,fs_vfstype| remote_fs?(fs_vfstype) }.keys
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def local
|
|
44
|
+
@mounts.select { |fs_file,fs_vfstype| local_fs?(fs_vfstype) }.keys
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def all
|
|
48
|
+
@mounts.keys
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def parse_mounts(proc_mounts)
|
|
55
|
+
# /proc/mounts can contain multiple lines for the same fs_file
|
|
56
|
+
# we store the latest entry only, because that's the relevant one
|
|
57
|
+
mounts = Hash.new
|
|
58
|
+
proc_mounts.each_line do |line|
|
|
59
|
+
fs_spec, fs_file, fs_vfstype, fs_mntops, fs_freq, fs_passno = line.split(' ')
|
|
60
|
+
mounts[fs_file] = fs_vfstype
|
|
61
|
+
end
|
|
62
|
+
mounts
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def remote_fs?(fs)
|
|
66
|
+
REMOTE_FILE_SYSTEMS.include?(fs)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def local_fs?(fs)
|
|
70
|
+
LOCAL_FILE_SYSTEMS.include?(fs)
|
|
71
|
+
end
|
|
72
|
+
end
|
data/lib/object.rb
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
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
|
+
class Object
|
|
20
|
+
class << self
|
|
21
|
+
def has_property(name, options)
|
|
22
|
+
@property_classes ||= {}
|
|
23
|
+
@property_classes[name.to_sym] = options[:class]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def from_json(json)
|
|
27
|
+
return nil unless json
|
|
28
|
+
|
|
29
|
+
entries = json.map do |key, value|
|
|
30
|
+
value_converted = if @property_classes && @property_classes[key.to_sym]
|
|
31
|
+
@property_classes[key.to_sym].from_json(value)
|
|
32
|
+
else
|
|
33
|
+
case value
|
|
34
|
+
when ::Array
|
|
35
|
+
Machinery::Array.from_json(value)
|
|
36
|
+
when Hash
|
|
37
|
+
Machinery::Object.from_json(value)
|
|
38
|
+
else
|
|
39
|
+
value
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
[key, value_converted]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
new(Hash[entries])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
attr_reader :attributes
|
|
51
|
+
|
|
52
|
+
def initialize(attrs = {})
|
|
53
|
+
@attributes = attrs.inject({}) do |attributes, (key, value)|
|
|
54
|
+
key = key.to_sym if key.respond_to?(:to_sym)
|
|
55
|
+
|
|
56
|
+
attributes[key] = value
|
|
57
|
+
attributes
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ==(other)
|
|
62
|
+
self.class == other.class && @attributes == other.attributes
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Various Array operators such as "-" and "&" use #eql? and #hash to compare
|
|
66
|
+
# array elements, which is why we need to make sure they work properly.
|
|
67
|
+
|
|
68
|
+
alias eql? ==
|
|
69
|
+
|
|
70
|
+
def hash
|
|
71
|
+
@attributes.hash
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def [](key)
|
|
75
|
+
@attributes[key.to_sym]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def []=(key, value)
|
|
79
|
+
@attributes[key.to_sym] = value
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def empty?
|
|
83
|
+
@attributes.keys.empty?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def method_missing(name, *args, &block)
|
|
87
|
+
if name.to_s.end_with?("=")
|
|
88
|
+
if args.size != 1
|
|
89
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 1)"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
@attributes[name.to_s[0..-2].to_sym] = args.first
|
|
93
|
+
else
|
|
94
|
+
if @attributes.has_key?(name)
|
|
95
|
+
if !args.empty?
|
|
96
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 0)"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@attributes[name]
|
|
100
|
+
else
|
|
101
|
+
nil
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def respond_to?(name, include_all = false)
|
|
107
|
+
if name.to_s.end_with?("=")
|
|
108
|
+
true
|
|
109
|
+
else
|
|
110
|
+
@attributes.has_key?(name) || super(name, include_all)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def initialize_copy(orig)
|
|
115
|
+
super
|
|
116
|
+
@attributes = @attributes.dup
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def as_json
|
|
120
|
+
entries = @attributes.map do |key, value|
|
|
121
|
+
case value
|
|
122
|
+
when Machinery::Array, Machinery::Object
|
|
123
|
+
value_json = value.as_json
|
|
124
|
+
else
|
|
125
|
+
value_json = value
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
[key, value_json]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
Hash[entries]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def compare_with(other)
|
|
135
|
+
self == other ? [nil, nil, self] : [self, other, nil]
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
data/lib/os.rb
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
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 Os
|
|
19
|
+
attr_reader :can_build, :name
|
|
20
|
+
|
|
21
|
+
def self.descendants
|
|
22
|
+
ObjectSpace.each_object(::Class).select { |klass| klass < self }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.for(os_name)
|
|
26
|
+
descendants.each do |os_class|
|
|
27
|
+
os_object = os_class.new
|
|
28
|
+
if os_name == os_object.name
|
|
29
|
+
return os_object
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
raise Machinery::Errors::UnknownOs.new("Unknown OS: '#{os_name}'")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def can_build?(os)
|
|
36
|
+
if os.is_a?(Class)
|
|
37
|
+
return @can_build.include?(os)
|
|
38
|
+
else
|
|
39
|
+
return @can_build.include?(os.class)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def module_required_by_package(package)
|
|
44
|
+
if @module_required_by_package
|
|
45
|
+
return @module_required_by_package[package]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def can_run_machinery?
|
|
50
|
+
@can_run_machinery
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class OsSles11 < Os
|
|
55
|
+
def initialize
|
|
56
|
+
@can_build = []
|
|
57
|
+
@name = "SUSE Linux Enterprise Server 11"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class OsSles12 < Os
|
|
62
|
+
def initialize
|
|
63
|
+
@can_build = [OsSles12]
|
|
64
|
+
@name = "SUSE Linux Enterprise Server 12"
|
|
65
|
+
@module_required_by_package = {
|
|
66
|
+
"python-glanceclient" => "Public Cloud Module"
|
|
67
|
+
}
|
|
68
|
+
@can_run_machinery = true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class OsOpenSuse13_1 < Os
|
|
73
|
+
def initialize
|
|
74
|
+
@can_build = [OsSles11, OsOpenSuse13_1]
|
|
75
|
+
@name = "openSUSE 13.1 (Bottle)"
|
|
76
|
+
@can_run_machinery = true
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
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 RemoteSystem < System
|
|
19
|
+
attr_accessor :host
|
|
20
|
+
|
|
21
|
+
def initialize(host)
|
|
22
|
+
@host = host
|
|
23
|
+
|
|
24
|
+
connect
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def requires_root?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def run_command(*args)
|
|
32
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
33
|
+
|
|
34
|
+
# There are three valid ways how to call Cheetah.run, whose interface this
|
|
35
|
+
# method mimics. The following code ensures that the "commands" variable
|
|
36
|
+
# consistently (in all three cases) contains an array of arrays specifying
|
|
37
|
+
# commands and their arguments.
|
|
38
|
+
#
|
|
39
|
+
# See comment in Cheetah.build_commands for more detailed explanation:
|
|
40
|
+
#
|
|
41
|
+
# https://github.com/openSUSE/cheetah/blob/0cd3f88c1210305e87dfc4852bb83040e82d783f/lib/cheetah.rb#L395
|
|
42
|
+
#
|
|
43
|
+
commands = args.all? { |a| a.is_a?(Array) } ? args : [args]
|
|
44
|
+
|
|
45
|
+
# When ssh executes commands, it passes them through shell expansion. For
|
|
46
|
+
# example, compare
|
|
47
|
+
#
|
|
48
|
+
# $ echo '$HOME'
|
|
49
|
+
# $HOME
|
|
50
|
+
#
|
|
51
|
+
# with
|
|
52
|
+
#
|
|
53
|
+
# $ ssh localhost echo '$HOME'
|
|
54
|
+
# /home/dmajda
|
|
55
|
+
#
|
|
56
|
+
# To mitigate that and maintain usual Cheetah semantics, we need to protect
|
|
57
|
+
# the command and its arguments using another layer of escaping.
|
|
58
|
+
escaped_commands = commands.map do |command|
|
|
59
|
+
command.map { |c| Shellwords.escape(c) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Arrange the commands in a way that allows piped commands trough ssh.
|
|
63
|
+
piped_args = escaped_commands[0..-2].flat_map do |command|
|
|
64
|
+
[*command, "|"]
|
|
65
|
+
end + escaped_commands.last
|
|
66
|
+
|
|
67
|
+
if options[:disable_logging]
|
|
68
|
+
cheetah_class = Cheetah
|
|
69
|
+
else
|
|
70
|
+
cheetah_class = LoggedCheetah
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
cheetah_class.run("ssh", "root@#{host}", "LC_ALL=C", *piped_args, options)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Tries to connect to the remote system as root (without a password or passphrase)
|
|
77
|
+
# and raises an Machinery::Errors::SshConnectionFailed exception when it's not successful.
|
|
78
|
+
def connect
|
|
79
|
+
LoggedCheetah.run "ssh", "-q", "-o", "BatchMode=yes", "root@#{host}"
|
|
80
|
+
rescue Cheetah::ExecutionFailed
|
|
81
|
+
raise Machinery::Errors::SshConnectionFailed.new(
|
|
82
|
+
"Could not establish SSH connection to host '#{host}'. Please make sure that " \
|
|
83
|
+
"you can connect non-interactively as root, e.g. using ssh-agent."
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Retrieves files specified in filelist from the remote system and raises an
|
|
89
|
+
# Machinery::Errors::RsyncFailed exception when it's not successful. Destination is
|
|
90
|
+
# the directory where to put the files.
|
|
91
|
+
def retrieve_files(filelist, destination)
|
|
92
|
+
source="root@#{host}:/"
|
|
93
|
+
begin
|
|
94
|
+
LoggedCheetah.run("rsync", "-e", "ssh", "--chmod=go-rwx", "--files-from=-", source, destination, :stdout => :capture, :stdin => filelist.join("\n") )
|
|
95
|
+
rescue Cheetah::ExecutionFailed => e
|
|
96
|
+
raise Machinery::Errors::RsyncFailed.new(
|
|
97
|
+
"Could not rsync files from host '#{host}'.\n" \
|
|
98
|
+
"Error: #{e}"
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Reads a file from the System. Returns nil if it does not exist.
|
|
104
|
+
def read_file(file)
|
|
105
|
+
run_command("cat", file, stdout: :capture)
|
|
106
|
+
rescue Cheetah::ExecutionFailed => e
|
|
107
|
+
if e.status.exitstatus == 1
|
|
108
|
+
# File not found, return nil
|
|
109
|
+
return
|
|
110
|
+
else
|
|
111
|
+
raise
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
data/lib/remove_task.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
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 RemoveTask
|
|
19
|
+
def remove(store, name, options = {})
|
|
20
|
+
if !options[:all] && !store.list.include?(name)
|
|
21
|
+
raise Machinery::Errors::SystemDescriptionNotFound.new(
|
|
22
|
+
"System description \"#{name}\" does not exist."
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if options[:all]
|
|
27
|
+
removed_descriptions = store.list
|
|
28
|
+
removed_descriptions.each do |name|
|
|
29
|
+
store.remove(name)
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
store.remove(name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if options[:verbose]
|
|
36
|
+
if options[:all]
|
|
37
|
+
Machinery::Ui.puts "Removed #{removed_descriptions.length} system descriptions successfully."
|
|
38
|
+
else
|
|
39
|
+
Machinery::Ui.puts "System description \"#{name}\" successfully removed."
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|