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.
- 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
|