machinery-tool 1.13.0 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.git_revision +1 -0
  3. data/NEWS +10 -0
  4. data/bin/machinery +7 -1
  5. data/{helpers → filters}/default_filters.json +0 -0
  6. data/{helpers → filters}/filter-packages-for-build.yaml +0 -0
  7. data/{helpers → inspect_helpers}/changed_files.sh +0 -0
  8. data/{helpers → inspect_helpers}/yum_repositories.py +0 -0
  9. data/lib/cli.rb +136 -52
  10. data/lib/compare_task.rb +1 -1
  11. data/lib/constants.rb +1 -1
  12. data/lib/docker_system.rb +135 -0
  13. data/lib/exceptions.rb +3 -2
  14. data/lib/filter.rb +1 -1
  15. data/lib/hint.rb +8 -2
  16. data/lib/inspect_task.rb +3 -3
  17. data/lib/kiwi_config.rb +2 -2
  18. data/lib/list_task.rb +14 -7
  19. data/lib/local_system.rb +20 -2
  20. data/lib/machinery.rb +2 -0
  21. data/lib/machinery_helper.rb +17 -14
  22. data/lib/move_task.rb +22 -0
  23. data/lib/remote_system.rb +4 -0
  24. data/lib/scope_file_access_archive.rb +10 -0
  25. data/lib/scope_file_access_flat.rb +4 -0
  26. data/lib/show_task.rb +1 -1
  27. data/lib/system.rb +16 -2
  28. data/lib/system_description.rb +19 -9
  29. data/lib/system_description_store.rb +10 -0
  30. data/lib/version.rb +1 -1
  31. data/lib/workload_mapper.rb +2 -1
  32. data/machinery-helper/README.md +13 -0
  33. data/machinery-helper/Rakefile +124 -0
  34. data/machinery-helper/machinery_helper.go +228 -0
  35. data/machinery-helper/machinery_helper_test.go +192 -0
  36. data/machinery-helper/mountpoints.go +81 -0
  37. data/machinery-helper/mountpoints_test.go +74 -0
  38. data/machinery-helper/tar.go +142 -0
  39. data/machinery-helper/version.go +5 -0
  40. data/man/generated/machinery.1.gz +0 -0
  41. data/man/generated/machinery.1.html +43 -6
  42. data/plugins/changed_managed_files/changed_managed_files_inspector.rb +1 -1
  43. data/plugins/config_files/config_files_inspector.rb +1 -1
  44. data/plugins/config_files/config_files_renderer.rb +1 -1
  45. data/plugins/environment/environment_inspector.rb +2 -2
  46. data/plugins/environment/schema/system-description-environment.schema-v5.json +4 -0
  47. data/plugins/os/os_inspector.rb +23 -11
  48. data/plugins/repositories/repositories_inspector.rb +1 -1
  49. data/plugins/services/services_inspector.rb +6 -1
  50. data/plugins/unmanaged_files/unmanaged_files_inspector.rb +35 -30
  51. data/plugins/unmanaged_files/unmanaged_files_model.rb +12 -6
  52. data/workload_mapper/docker-registry/clue.rb +0 -2
  53. data/workload_mapper/docker-registry/compose-template.yml +2 -1
  54. data/workload_mapper/docker-registry/container/Dockerfile +1 -1
  55. data/workload_mapper/mariadb/clue.rb +1 -0
  56. data/workload_mapper/mariadb/compose-template.yml +2 -2
  57. data/workload_mapper/rails/compose-template.yml +0 -1
  58. data/workload_mapper/rails/container/Dockerfile +3 -4
  59. data/workload_mapper/wordpress/clue.rb +13 -0
  60. data/workload_mapper/wordpress/compose-template.yml +5 -0
  61. data/workload_mapper/wordpress/config/wp-config.php +38 -0
  62. data/workload_mapper/wordpress/container/Dockerfile +25 -0
  63. data/workload_mapper/wordpress/container/apache2/listen.conf +1 -0
  64. data/workload_mapper/wordpress/container/apache2/wordpress_vhost.conf +21 -0
  65. data/workload_mapper/wordpress/setup/setup.rb.erb +67 -0
  66. metadata +26 -8
  67. data/helpers/inspector_files.rb +0 -52
@@ -0,0 +1,192 @@
1
+ // Copyright (c) 2015 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
+ package main
19
+
20
+ import (
21
+ "testing"
22
+ "reflect"
23
+ "os"
24
+ "time"
25
+ "github.com/nowk/go-fakefileinfo"
26
+ )
27
+
28
+ func doTestParseRpmLine(t *testing.T, line string, expectedFileType string, expectedFileName string, expectedLinkTarget string) {
29
+ fileType, fileName, linkTarget := parseRpmLine(line)
30
+
31
+ if fileType != expectedFileType {
32
+ t.Errorf("parseRpmLine('%s') file type = '%s', want '%s'", line, fileType, expectedFileType)
33
+ }
34
+ if fileName != expectedFileName {
35
+ t.Errorf("parseRpmLine('%s') file name = '%s', want '%s'", line, fileName, expectedFileName)
36
+ }
37
+ if linkTarget != expectedLinkTarget {
38
+ t.Errorf("parseRpmLine('%s') file type = '%s', want '%s'", line, linkTarget, expectedLinkTarget)
39
+ }
40
+ }
41
+
42
+ func TestParseRpmLineFile(t *testing.T) {
43
+ line := "-rw-r--r-- 1 root root 18234080 Mar 31 11:40 /usr/lib64/libruby2.0-static.a"
44
+
45
+ expectedFileType := "-"
46
+ expectedFileName := "/usr/lib64/libruby2.0-static.a"
47
+ expectedLinkTarget := ""
48
+
49
+ doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
50
+ }
51
+
52
+ func TestParseRpmLineDir(t *testing.T) {
53
+ line := "drwxr-xr-x 2 root root 0 Mar 31 11:45 /usr/include/ruby-2.0.0/x86_64-linux/ruby"
54
+
55
+ expectedFileType := "d"
56
+ expectedFileName := "/usr/include/ruby-2.0.0/x86_64-linux/ruby"
57
+ expectedLinkTarget := ""
58
+
59
+ doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
60
+ }
61
+
62
+ func TestParseRpmLineLink(t *testing.T) {
63
+ line := "lrwxrwxrwx 1 root root 19 Mar 31 11:45 /usr/lib64/libruby2.0.so -> libruby2.0.so.2.0.0"
64
+
65
+ expectedFileType := "l"
66
+ expectedFileName := "/usr/lib64/libruby2.0.so"
67
+ expectedLinkTarget := "libruby2.0.so.2.0.0"
68
+
69
+ doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
70
+ }
71
+
72
+ func TestParseRpmLineFileSpaces(t *testing.T) {
73
+ line := "-rw-r--r-- 1 root root 61749 Jun 26 01:56 /usr/share/kde4/templates/kipiplugins_photolayoutseditor/data/templates/a4/h/Flipping Tux Black.ple"
74
+
75
+ expectedFileType := "-"
76
+ expectedFileName := "/usr/share/kde4/templates/kipiplugins_photolayoutseditor/data/templates/a4/h/Flipping Tux Black.ple"
77
+ expectedLinkTarget := ""
78
+
79
+ doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
80
+ }
81
+
82
+ func TestAddImplicitlyManagedDirs(t *testing.T) {
83
+ filesOriginal := map[string]string{
84
+ "/abc/def/ghf/somefile": "",
85
+ "/zzz": "/abc/def",
86
+ }
87
+ dirsOriginal := map[string]bool{
88
+ "/abc/def": true,
89
+ }
90
+ dirsExpected := map[string]bool{
91
+ "/abc": false,
92
+ "/abc/def": true,
93
+ "/abc/def/ghf": false,
94
+ "/zzz": false,
95
+ }
96
+
97
+ dirs := dirsOriginal
98
+
99
+ addImplicitlyManagedDirs(dirs, filesOriginal)
100
+
101
+ if !reflect.DeepEqual(dirs, dirsExpected) {
102
+ t.Errorf("addImplicitlyManagedDirs('%v') = '%v', want '%v'", dirsOriginal, dirs, dirsExpected)
103
+ }
104
+ }
105
+
106
+ func TestAssembleJSON(t *testing.T) {
107
+ unmanagedFilesMap := map[string]string{
108
+ "name": "/usr/share/go_rulez", "type":"file",
109
+ }
110
+ want := `{
111
+ "extracted": false,
112
+ "files": {
113
+ "name": "/usr/share/go_rulez",
114
+ "type": "file"
115
+ }
116
+ }`
117
+
118
+ json := assembleJSON(unmanagedFilesMap)
119
+ if !reflect.DeepEqual(json, want) {
120
+ t.Errorf("assembleJSON() = '%v', want '%v'", json, want)
121
+ }
122
+ }
123
+
124
+ func TestRespectManagedDirsInUnmanagedDirs(t *testing.T) {
125
+ unmanagedFiles := make(map[string]string)
126
+ wantUnmanagedFiles := make(map[string]string)
127
+
128
+ /*
129
+ We mock the readDir method and return following directory structure:
130
+ /
131
+ /managed_dir/
132
+ /managed_dir/unmanaged_dir/
133
+ /managed_dir/unmanaged_dir/managed_dir/
134
+ */
135
+ readDir = func(dir string) ([]os.FileInfo, error) {
136
+ dirs := make([]os.FileInfo, 0, 1)
137
+ var fi os.FileInfo
138
+ switch dir {
139
+ case "/":
140
+ fi = fakefileinfo.New("managed_dir", int64(123), os.ModeType, time.Now(), true, nil)
141
+ case "/managed_dir/":
142
+ fi = fakefileinfo.New("unmanaged_dir", int64(123), os.ModeType, time.Now(), true, nil)
143
+ case "/managed_dir/unmanaged_dir/":
144
+ fi = fakefileinfo.New("managed_dir", int64(123), os.ModeType, time.Now(), true, nil)
145
+ }
146
+ dirs = append (dirs, fi)
147
+ return dirs, nil
148
+ }
149
+
150
+ rpmFiles := make(map[string]string)
151
+ ignoreList := make(map[string]bool)
152
+
153
+ rpmDirs := map[string]bool{
154
+ "/managed_dir": true,
155
+ "/managed_dir/unmanaged_dir/managed_dir": true,
156
+ }
157
+
158
+ findUnmanagedFiles("/", rpmFiles, rpmDirs, unmanagedFiles, ignoreList)
159
+
160
+ if !reflect.DeepEqual(unmanagedFiles, wantUnmanagedFiles) {
161
+ t.Errorf("findUnmanagedFiles() = '%v', want '%v'", unmanagedFiles, wantUnmanagedFiles)
162
+ }
163
+ }
164
+
165
+ func TestHasManagedDirs(t *testing.T) {
166
+ rpmDirs := map[string]bool{
167
+ "/managed_dir": true,
168
+ "/managed_dir/unmanaged_dir/sub_dir/managed_dir": true,
169
+ }
170
+
171
+ hasDirs := hasManagedDirs("/managed_dir/unmanaged_dir", rpmDirs)
172
+ want := true
173
+
174
+ if hasDirs != want {
175
+ t.Errorf("hasManagedDirs() = '%v', want '%v'", hasDirs, want)
176
+ }
177
+
178
+ }
179
+
180
+ func TestSubdirIsNotAccidentallyConsideredManaged(t *testing.T) {
181
+ rpmDirs := map[string]bool{
182
+ "/usr": true,
183
+ "/usr/foobar": true,
184
+ }
185
+
186
+ hasDirs := hasManagedDirs("/usr/foo", rpmDirs)
187
+ want := false
188
+
189
+ if hasDirs != want {
190
+ t.Errorf("hasManagedDirs() = '%v', want '%v'", hasDirs, want)
191
+ }
192
+ }
@@ -0,0 +1,81 @@
1
+ // Copyright (c) 2015 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
+ package main
19
+
20
+ import (
21
+ "io/ioutil"
22
+ "strings"
23
+ "sort"
24
+ )
25
+
26
+ // this specifies the path of the process mounts. This needs to be
27
+ // exported for the test cases
28
+ var ProcMountsPath = "/proc/mounts"
29
+
30
+ var remoteFileSystems = []string{"autofs", "cifs", "nfs", "nfs4"}
31
+ var specialFileSystems = []string{"proc", "sysfs", "devtmpfs", "tmpfs", "rpc_pipefs", "fuse.gvfs-fuse-daemon"}
32
+ var localFileSystems = []string{"ext2", "ext3", "ext4", "reiserfs", "btrfs", "vfat", "xfs", "jfs"}
33
+
34
+ func parseMounts() map[string]string {
35
+ mount, _ := ioutil.ReadFile(ProcMountsPath)
36
+ mounts := make(map[string]string)
37
+
38
+ lines := strings.Split(string(mount), "\n")
39
+
40
+ for _, line := range(lines) {
41
+ elements := strings.Split(line, " ")
42
+
43
+ if len(elements) >= 3 {
44
+ mounts[elements[1]] = elements[2]
45
+ }
46
+ }
47
+
48
+ return mounts
49
+ }
50
+
51
+ func selectFileSystems(allMounts map[string]string, fileSystems[]string) []string {
52
+ mounts := []string{}
53
+
54
+ for path, fs := range(allMounts) {
55
+ for _, specialFs := range fileSystems {
56
+ if specialFs == fs {
57
+ mounts = append(mounts, path)
58
+ }
59
+ }
60
+ }
61
+ sort.Strings(mounts)
62
+
63
+ return mounts
64
+ }
65
+
66
+ // SpecialMounts returns an array of all special mount paths like
67
+ // proc or sysfs
68
+ func SpecialMounts() []string {
69
+ return selectFileSystems(parseMounts(), specialFileSystems)
70
+ }
71
+
72
+ // LocalMounts returns an array of all local mount paths
73
+ func LocalMounts() []string {
74
+ return selectFileSystems(parseMounts(), localFileSystems)
75
+ }
76
+
77
+ // RemoteMounts returns an array of all remote mount paths
78
+ // (for example NFS mount points)
79
+ func RemoteMounts() []string {
80
+ return selectFileSystems(parseMounts(), remoteFileSystems)
81
+ }
@@ -0,0 +1,74 @@
1
+ // Copyright (c) 2015 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
+ package main
19
+
20
+ import (
21
+ "testing"
22
+ "reflect"
23
+ )
24
+
25
+ func TestParseMounts(t *testing.T) {
26
+ ProcMountsPath = "fixtures/proc_mounts"
27
+
28
+ expectedMounts := map[string]string{
29
+ "/dev": "devtmpfs",
30
+ "/homes/tux": "nfs",
31
+ "/data": "ext4",
32
+ "/": "ext4",
33
+ "/var/lib/ntp/proc": "proc",
34
+ "/var/lib/tmpfs": "tmpfs",
35
+ }
36
+
37
+ actualMounts := parseMounts()
38
+ if !reflect.DeepEqual(actualMounts, expectedMounts) {
39
+ t.Errorf("Expected: ", expectedMounts, " Got: ", actualMounts)
40
+ }
41
+ }
42
+
43
+ func TestSpecialMounts(t *testing.T) {
44
+ ProcMountsPath = "fixtures/proc_mounts"
45
+
46
+ expectedMounts := []string{"/dev", "/var/lib/ntp/proc", "/var/lib/tmpfs"}
47
+ actualMounts := SpecialMounts()
48
+
49
+ if !reflect.DeepEqual(actualMounts, expectedMounts) {
50
+ t.Errorf("Expected: ", expectedMounts, " Got: ", actualMounts)
51
+ }
52
+ }
53
+
54
+ func TestLocalMounts(t *testing.T) {
55
+ ProcMountsPath = "fixtures/proc_mounts"
56
+
57
+ expectedMounts := []string{"/", "/data"}
58
+ actualMounts := LocalMounts()
59
+
60
+ if !reflect.DeepEqual(actualMounts, expectedMounts) {
61
+ t.Errorf("Expected: ", expectedMounts, " Got: ", actualMounts)
62
+ }
63
+ }
64
+
65
+ func TestRemoteMounts(t *testing.T) {
66
+ ProcMountsPath = "fixtures/proc_mounts"
67
+
68
+ expectedMounts := []string{"/homes/tux"}
69
+ actualMounts := RemoteMounts()
70
+
71
+ if !reflect.DeepEqual(actualMounts, expectedMounts) {
72
+ t.Errorf("Expected: ", expectedMounts, " Got: ", actualMounts)
73
+ }
74
+ }
@@ -0,0 +1,142 @@
1
+ // Copyright (c) 2015 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
+ package main
19
+
20
+ import (
21
+ "flag"
22
+ "os"
23
+ "io"
24
+ "bufio"
25
+ "strings"
26
+ "archive/tar"
27
+ "compress/gzip"
28
+ "fmt"
29
+ "path/filepath"
30
+ "os/user"
31
+ "strconv"
32
+ "os/exec"
33
+ )
34
+
35
+ type stringArrayFlag []string
36
+ func (i *stringArrayFlag) String() string {
37
+ return "exclude"
38
+ }
39
+ func (i *stringArrayFlag) Set(value string) error {
40
+ *i = append(*i, value)
41
+ return nil
42
+ }
43
+
44
+ var excludeList = make(map[string]bool)
45
+ var gzipWriter = gzip.NewWriter(os.Stdout)
46
+ var tarWriter = tar.NewWriter(gzipWriter)
47
+
48
+ func addPath(path string, info os.FileInfo, err error) error {
49
+ if err != nil {
50
+ return err
51
+ }
52
+
53
+ if stat, err := os.Lstat(path); err == nil {
54
+ if _, ok := excludeList[strings.TrimRight(path, "/")]; ok {
55
+ return nil
56
+ }
57
+
58
+ linkTarget := ""
59
+ if(stat.Mode() & os.ModeSymlink != 0) {
60
+ if linkTarget, err= os.Readlink(path); err != nil {
61
+ return err
62
+ }
63
+ }
64
+ header, err := tar.FileInfoHeader(stat, linkTarget)
65
+ header.Name = strings.TrimLeft(path, "/")
66
+ if err != nil {
67
+ return err
68
+ }
69
+
70
+ username, err := user.LookupId(strconv.Itoa(header.Uid))
71
+ if err != nil {
72
+ return err
73
+ }
74
+ header.Uname = username.Username
75
+
76
+ groupname, err := exec.Command("bash", "-c",
77
+ fmt.Sprintf("getent group %d | cut -d: -f1", header.Gid)).Output()
78
+ if err != nil {
79
+ return err
80
+ }
81
+ header.Gname = strings.TrimSpace(string(groupname))
82
+
83
+ if err := tarWriter.WriteHeader(header); err != nil {
84
+ return err
85
+ }
86
+
87
+ if stat.Mode().IsRegular() {
88
+ file, err := os.Open(path)
89
+ if err != nil {
90
+ return err
91
+ }
92
+ defer file.Close()
93
+
94
+ if _, err := io.Copy(tarWriter, file); err != nil {
95
+ return err
96
+ }
97
+ }
98
+ }
99
+ return nil
100
+ }
101
+
102
+ // Tar represents the "tar" command for the machinery-helper
103
+ func Tar(args []string) {
104
+ var files []string
105
+ tarCommand := flag.NewFlagSet("tar", flag.ExitOnError)
106
+ tarCommand.Bool("create", true, "Create an tar archive")
107
+ tarCommand.Bool("gzip", true, "Compress archive using GZip")
108
+ tarCommand.Bool("null", true, "Read null-terminated names")
109
+ filesFromFlag := tarCommand.String("files-from", "", "Where to take the file list from")
110
+
111
+ var excludeFlag stringArrayFlag
112
+ tarCommand.Var(&excludeFlag, "exclude", "Read null-terminated names")
113
+
114
+ tarCommand.Parse(args)
115
+ for _, path := range(excludeFlag) {
116
+ excludeList[path] = true
117
+ }
118
+
119
+ if(*filesFromFlag == "-") {
120
+ reader := bufio.NewReader(os.Stdin)
121
+
122
+ for {
123
+ s, err := reader.ReadString('\x00')
124
+
125
+ files = append(files, strings.TrimRight(strings.TrimSpace(s), "\x00"))
126
+
127
+ if err == io.EOF {
128
+ break
129
+ }
130
+ }
131
+ } else {
132
+ files = tarCommand.Args()
133
+ }
134
+
135
+ for i := range files {
136
+ if err := filepath.Walk(files[i], addPath); err != nil {
137
+ fmt.Fprintln(os.Stderr, "Error:", err)
138
+ }
139
+ }
140
+ defer gzipWriter.Close()
141
+ defer tarWriter.Close()
142
+ }
@@ -0,0 +1,5 @@
1
+ // This is a generated file and shouldn't be changed
2
+
3
+ package main
4
+
5
+ const VERSION = "9787fc1eff835522740423ff35c98b78205b31cb"
Binary file
@@ -58,6 +58,7 @@
58
58
  <a href="#WORK-FLOW-EXAMPLES">WORK FLOW EXAMPLES</a>
59
59
  <a href="#CONCEPTUAL-OVERVIEW">CONCEPTUAL OVERVIEW</a>
60
60
  <a href="#OPTIONS-FOR-ALL-SUBCOMMANDS">OPTIONS FOR ALL SUBCOMMANDS</a>
61
+ <a href="#analyze-Analyze-System-Description">analyze — Analyze System Description</a>
61
62
  <a href="#build-Build-Image-from-System-Description">build — Build Image from System Description</a>
62
63
  <a href="#compare-Compare-System-Descriptions">compare — Compare System Descriptions</a>
63
64
  <a href="#config-Configure-Machinery">config — Configure Machinery</a>
@@ -68,6 +69,7 @@
68
69
  <a href="#inspect-Inspect-Running-System">inspect — Inspect Running System</a>
69
70
  <a href="#list-List-System-Descriptions">list — List System Descriptions</a>
70
71
  <a href="#man-Shows-Man-Page">man — Shows Man Page</a>
72
+ <a href="#move-Move-System-Description">move — Move System Description</a>
71
73
  <a href="#remove-Remove-System-Descriptions">remove — Remove System Descriptions</a>
72
74
  <a href="#serve-Serve-A-System-Description-Using-A-Web-Server">serve — Serve A System Description Using A Web Server</a>
73
75
  <a href="#show-Show-System-Description">show — Show System Description</a>
@@ -373,7 +375,7 @@ file which can be useful to track down problems.</p></dd>
373
375
  </dl>
374
376
 
375
377
 
376
- <h1>analyze — Analyze System Description</h1>
378
+ <h2 id="analyze-Analyze-System-Description">analyze — Analyze System Description</h2>
377
379
 
378
380
  <h3 id="SYNOPSIS">SYNOPSIS</h3>
379
381
 
@@ -854,7 +856,7 @@ via <code>ssh-copy-id</code> to the inspected host, e.g.: <code>ssh-copy-id root
854
856
 
855
857
  <ul>
856
858
  <li><code>rpm</code></li>
857
- <li><code>zypper</code></li>
859
+ <li><code>zypper</code> or <code>yum</code></li>
858
860
  <li><code>rsync</code></li>
859
861
  <li><code>chkconfig</code></li>
860
862
  <li><code>cat</code></li>
@@ -902,13 +904,15 @@ configuration files are saved:</p>
902
904
 
903
905
  <h3 id="SYNOPSIS">SYNOPSIS</h3>
904
906
 
905
- <p><code>machinery list</code></p>
907
+ <p><code>machinery list</code>
908
+ [NAME[,NAME2[,NAME3]]]</p>
906
909
 
907
910
  <p><code>machinery</code> help list</p>
908
911
 
909
912
  <h3 id="DESCRIPTION">DESCRIPTION</h3>
910
913
 
911
- <p>List all available system descriptions in the internal database.
914
+ <p>List the specified system descriptions if parameter name is given.
915
+ List all available system descriptions in the internal database if no name parameter is given.
912
916
  The list is sorted alphabetically and contains a name and the
913
917
  scopes for each system.</p>
914
918
 
@@ -924,6 +928,9 @@ Currently displays [HOSTNAME] and (DATE).</dd>
924
928
  <h3 id="EXAMPLES">EXAMPLES</h3>
925
929
 
926
930
  <dl>
931
+ <dt>Lists the two specified system descriptions <code>a</code> and <code>b</code>:</dt><dd><p></p>
932
+
933
+ <p>$ <code>machinery</code> list a b</p></dd>
927
934
  <dt>Lists all available system descriptions:</dt><dd><p></p>
928
935
 
929
936
  <p>$ <code>machinery</code> list</p></dd>
@@ -946,12 +953,42 @@ Currently displays [HOSTNAME] and (DATE).</dd>
946
953
 
947
954
  <p>The <code>man</code> command shows the Machinery man page.</p>
948
955
 
956
+ <h2 id="move-Move-System-Description">move — Move System Description</h2>
957
+
958
+ <h3 id="SYNOPSIS">SYNOPSIS</h3>
959
+
960
+ <p><code>machinery move</code>
961
+ FROM_NAME TO_NAME</p>
962
+
963
+ <p><code>machinery</code> help move</p>
964
+
965
+ <h3 id="DESCRIPTION">DESCRIPTION</h3>
966
+
967
+ <p>The <code>move</code> command renames a stored system description from <code>FROM_NAME</code> to <code>TO_NAME</code>.</p>
968
+
969
+ <h3 id="ARGUMENTS">ARGUMENTS</h3>
970
+
971
+ <dl>
972
+ <dt><code>FROM_NAME</code> (required)</dt><dd><p>Current name of the system description.</p></dd>
973
+ <dt><code>TO_NAME</code> (required)</dt><dd><p>New name of the system description.</p></dd>
974
+ </dl>
975
+
976
+
977
+ <h3 id="EXAMPLES">EXAMPLES</h3>
978
+
979
+ <dl>
980
+ <dt>Rename the system description <code>earth</code> to <code>moon</code>:</dt><dd><p></p>
981
+
982
+ <p>$ <code>machinery</code> move earth moon</p></dd>
983
+ </dl>
984
+
985
+
949
986
  <h2 id="remove-Remove-System-Descriptions">remove — Remove System Descriptions</h2>
950
987
 
951
988
  <h3 id="SYNOPSIS">SYNOPSIS</h3>
952
989
 
953
990
  <p><code>machinery remove</code> [--all]
954
- NAME</p>
991
+ [NAME[,NAME2[,NAME3]]]</p>
955
992
 
956
993
  <p><code>machinery</code> help remove</p>
957
994
 
@@ -1217,7 +1254,7 @@ manually editing it.</p>
1217
1254
 
1218
1255
  <ol class='man-decor man-foot man foot'>
1219
1256
  <li class='tl'></li>
1220
- <li class='tc'>September 2015</li>
1257
+ <li class='tc'>October 2015</li>
1221
1258
  <li class='tr'>machinery(1)</li>
1222
1259
  </ol>
1223
1260
 
@@ -26,7 +26,7 @@ class ChangedManagedFilesInspector < Inspector
26
26
 
27
27
  def inspect(filter, options = {})
28
28
  system.check_requirement("find", "--version")
29
- system.check_requirement("rsync", "--version") if options[:extract_changed_managed_files]
29
+ system.check_retrieve_files_dependencies if options[:extract_changed_managed_files]
30
30
 
31
31
  @system = system
32
32
 
@@ -24,7 +24,7 @@ class ConfigFilesInspector < Inspector
24
24
  @system.check_requirement("rpm", "--version")
25
25
  @system.check_requirement("stat", "--version")
26
26
  @system.check_requirement("find", "--version")
27
- @system.check_requirement("rsync", "--version") if check_rsync
27
+ @system.check_retrieve_files_dependencies if check_rsync
28
28
  end
29
29
 
30
30
  # returns list of packages containing configfiles
@@ -24,7 +24,7 @@ class ConfigFilesRenderer < Renderer
24
24
  if !diffs_dir && @options[:show_diffs]
25
25
  raise Machinery::Errors::SystemDescriptionError.new(
26
26
  "Diffs can not be shown because they were not generated yet.\n" \
27
- "You can generate them with `#{$0} analyze" \
27
+ "You can generate them with `#{Hint.program_name} analyze" \
28
28
  " --operation=config-file-diffs #{description.name}`."
29
29
  )
30
30
  end
@@ -27,6 +27,7 @@ class EnvironmentInspector < Inspector
27
27
  environment = EnvironmentScope.new
28
28
 
29
29
  environment.locale = get_locale
30
+ environment.system_type = @system.type
30
31
 
31
32
  @description.environment = environment
32
33
  end
@@ -36,8 +37,7 @@ class EnvironmentInspector < Inspector
36
37
  def get_locale
37
38
  output = nil
38
39
  begin
39
- output = @system.run_command("locale", "-a", stdout: :capture)
40
- output.encode!("UTF-16be", invalid: :replace, undef: :replace, replace: "?").encode!("UTF-8")
40
+ output = Machinery.scrub(@system.run_command("locale", "-a", stdout: :capture))
41
41
  rescue
42
42
  return "C"
43
43
  end
@@ -7,6 +7,10 @@
7
7
  "locale": {
8
8
  "type": "string",
9
9
  "minLength": 1
10
+ },
11
+ "system_type": {
12
+ "type": "string",
13
+ "enum": ["local", "remote", "docker"]
10
14
  }
11
15
  }
12
16
  }