/
module_link.go
111 lines (88 loc) · 2.2 KB
/
module_link.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package modules
import (
"fmt"
"os"
"github.com/skx/marionette/config"
"github.com/skx/marionette/environment"
"github.com/skx/marionette/file"
)
// LinkModule stores our state
type LinkModule struct {
// cfg contains our configuration object.
cfg *config.Config
// env holds our environment
env *environment.Environment
}
// Check is part of the module-api, and checks arguments.
func (f *LinkModule) Check(args map[string]interface{}) error {
required := []string{"source", "target"}
for _, key := range required {
_, ok := args[key]
if !ok {
return fmt.Errorf("missing '%s' parameter", key)
}
}
return nil
}
// Execute is part of the module-api, and is invoked to run a rule.
func (f *LinkModule) Execute(args map[string]interface{}) (bool, error) {
// Get the target
target := StringParam(args, "target")
if target == "" {
return false, fmt.Errorf("failed to convert target to string")
}
// Get the source
source := StringParam(args, "source")
if source == "" {
return false, fmt.Errorf("failed to convert source to string")
}
// If the target doesn't exist we create the link.
if !file.Exists(target) {
err := os.Symlink(source, target)
return true, err
}
// If the target does exist see if it is correct.
fileInfo, err := os.Lstat(target)
if err != nil {
return false, err
}
// Is it a symlink?
if fileInfo.Mode()&os.ModeSymlink != 0 {
// If so get the target file to which it points.
var originFile string
originFile, err = os.Readlink(target)
if err != nil {
return false, err
}
// OK we have a target - is it correct?
if originFile == source {
return false, nil
}
// OK there is a symlink, but it points to the
// wrong target-file. Remove it.
err = os.Remove(target)
if err != nil {
return false, err
}
} else {
// We found something that wasn't a symlink.
//
// Remove it.
err = os.Remove(target)
if err != nil {
return false, err
}
}
// Fix the symlink.
err = os.Symlink(source, target)
return true, err
}
// init is used to dynamically register our module.
func init() {
Register("link", func(cfg *config.Config, env *environment.Environment) ModuleAPI {
return &LinkModule{
cfg: cfg,
env: env,
}
})
}