/
default-package.go
158 lines (130 loc) · 3.45 KB
/
default-package.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package pkg
import (
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"github.com/criteo/command-launcher/internal/command"
"gopkg.in/yaml.v3"
)
type defaultPackageManifest struct {
PkgName string `json:"pkgName" yaml:"pkgName"`
PkgVersion string `json:"version" yaml:"version"`
PkgCommands []*command.DefaultCommand `json:"cmds" yaml:"cmds"`
}
func (mf *defaultPackageManifest) Name() string {
return mf.PkgName
}
func (mf *defaultPackageManifest) Version() string {
return mf.PkgVersion
}
func (mf *defaultPackageManifest) Commands() []command.Command {
cmds := make([]command.Command, 0)
for _, cmd := range mf.PkgCommands {
//newCmd := cmd
cmds = append(cmds, cmd)
}
return cmds
}
type defaultPackage struct {
Manifest command.PackageManifest
// store the repository id, indicates which registry/repository that the package belongs to
repositoryID string
}
func (pkg *defaultPackage) Name() string {
return pkg.Manifest.Name()
}
func (pkg *defaultPackage) Version() string {
return pkg.Manifest.Version()
}
func (pkg *defaultPackage) Commands() []command.Command {
return pkg.Manifest.Commands()
}
func (pkg *defaultPackage) RepositoryID() string {
return pkg.repositoryID
}
func ReadManifest(file fs.File) (command.PackageManifest, error) {
stat, err := file.Stat()
if err != nil {
return nil, fmt.Errorf("cannot read the manifest file handle (%s)", err)
}
var payload = make([]byte, stat.Size())
nb, err := file.Read(payload)
if err != nil && err != io.EOF || nb != int(stat.Size()) {
return nil, fmt.Errorf("cannot read the manifest (%s)", err)
}
var mf = defaultPackageManifest{}
// YAML is super set of json, should work with JSON as well
err = yaml.Unmarshal(payload, &mf)
if err != nil {
return nil, fmt.Errorf("cannot read the manifest content, it is neither a valid JSON nor YAML (%s)", err)
}
return &mf, nil
}
func (pkg *defaultPackage) RunSetup(pkgDir string) error {
return ExecSetupHookFromPackage(pkg, pkgDir)
}
func copyFolder(srcFolder string, dstFolder string) error {
info, err := os.Stat(srcFolder)
if err != nil {
return err
}
if err = os.MkdirAll(dstFolder, info.Mode()); err != nil {
return err
}
files, err := os.ReadDir(srcFolder)
if err != nil {
return err
}
for _, fd := range files {
src := filepath.Join(srcFolder, fd.Name())
dst := filepath.Join(dstFolder, fd.Name())
if fd.IsDir() {
if err = copyFolder(src, dst); err != nil {
return err
}
} else {
if err = copyFile(src, dst); err != nil {
return err
}
}
}
return nil
}
func copyFile(src string, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return fmt.Errorf("file extraction failed: %s", err)
}
defer dstFile.Close()
if _, err = io.Copy(dstFile, srcFile); err != nil {
return err
}
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
return os.Chmod(dst, srcInfo.Mode())
}
func ExecSetupHookFromPackage(pkg command.PackageManifest, pkgDir string) error {
for _, c := range pkg.Commands() {
if c.Name() == "__setup__" && c.Type() == "system" {
if pkgDir != "" {
c.SetPackageDir(pkgDir)
}
// Execute the __setup__ hook
_, err := c.Execute(os.Environ())
if err != nil {
return fmt.Errorf("setup hook of package %s failed to execute: %v", pkg.Name(), err)
}
return nil
}
}
return fmt.Errorf("no setup hook found in the package")
}