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.
- checksums.yaml +4 -4
- data/.git_revision +1 -0
- data/NEWS +10 -0
- data/bin/machinery +7 -1
- data/{helpers → filters}/default_filters.json +0 -0
- data/{helpers → filters}/filter-packages-for-build.yaml +0 -0
- data/{helpers → inspect_helpers}/changed_files.sh +0 -0
- data/{helpers → inspect_helpers}/yum_repositories.py +0 -0
- data/lib/cli.rb +136 -52
- data/lib/compare_task.rb +1 -1
- data/lib/constants.rb +1 -1
- data/lib/docker_system.rb +135 -0
- data/lib/exceptions.rb +3 -2
- data/lib/filter.rb +1 -1
- data/lib/hint.rb +8 -2
- data/lib/inspect_task.rb +3 -3
- data/lib/kiwi_config.rb +2 -2
- data/lib/list_task.rb +14 -7
- data/lib/local_system.rb +20 -2
- data/lib/machinery.rb +2 -0
- data/lib/machinery_helper.rb +17 -14
- data/lib/move_task.rb +22 -0
- data/lib/remote_system.rb +4 -0
- data/lib/scope_file_access_archive.rb +10 -0
- data/lib/scope_file_access_flat.rb +4 -0
- data/lib/show_task.rb +1 -1
- data/lib/system.rb +16 -2
- data/lib/system_description.rb +19 -9
- data/lib/system_description_store.rb +10 -0
- data/lib/version.rb +1 -1
- data/lib/workload_mapper.rb +2 -1
- data/machinery-helper/README.md +13 -0
- data/machinery-helper/Rakefile +124 -0
- data/machinery-helper/machinery_helper.go +228 -0
- data/machinery-helper/machinery_helper_test.go +192 -0
- data/machinery-helper/mountpoints.go +81 -0
- data/machinery-helper/mountpoints_test.go +74 -0
- data/machinery-helper/tar.go +142 -0
- data/machinery-helper/version.go +5 -0
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +43 -6
- data/plugins/changed_managed_files/changed_managed_files_inspector.rb +1 -1
- data/plugins/config_files/config_files_inspector.rb +1 -1
- data/plugins/config_files/config_files_renderer.rb +1 -1
- data/plugins/environment/environment_inspector.rb +2 -2
- data/plugins/environment/schema/system-description-environment.schema-v5.json +4 -0
- data/plugins/os/os_inspector.rb +23 -11
- data/plugins/repositories/repositories_inspector.rb +1 -1
- data/plugins/services/services_inspector.rb +6 -1
- data/plugins/unmanaged_files/unmanaged_files_inspector.rb +35 -30
- data/plugins/unmanaged_files/unmanaged_files_model.rb +12 -6
- data/workload_mapper/docker-registry/clue.rb +0 -2
- data/workload_mapper/docker-registry/compose-template.yml +2 -1
- data/workload_mapper/docker-registry/container/Dockerfile +1 -1
- data/workload_mapper/mariadb/clue.rb +1 -0
- data/workload_mapper/mariadb/compose-template.yml +2 -2
- data/workload_mapper/rails/compose-template.yml +0 -1
- data/workload_mapper/rails/container/Dockerfile +3 -4
- data/workload_mapper/wordpress/clue.rb +13 -0
- data/workload_mapper/wordpress/compose-template.yml +5 -0
- data/workload_mapper/wordpress/config/wp-config.php +38 -0
- data/workload_mapper/wordpress/container/Dockerfile +25 -0
- data/workload_mapper/wordpress/container/apache2/listen.conf +1 -0
- data/workload_mapper/wordpress/container/apache2/wordpress_vhost.conf +21 -0
- data/workload_mapper/wordpress/setup/setup.rb.erb +67 -0
- metadata +26 -8
- 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
|
+
}
|
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
|
-
<
|
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
|
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
|
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'>
|
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.
|
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.
|
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 `#{
|
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
|