machinery-tool 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
  }