103
109
return append(env, val)
106
// bundleTools bundles all the current juju tools in gzipped tar
107
// format to the given writer.
108
// If forceVersion is not nil, a FORCE-VERSION file is included in
109
// the tools bundle so it will lie about its current version number.
110
func bundleTools(w io.Writer, forceVersion *version.Number) (version.Binary, error) {
111
dir, err := ioutil.TempDir("", "juju-tools")
113
return version.Binary{}, err
115
defer os.RemoveAll(dir)
112
func findExecutable(execFile string) (string, error) {
113
logger.Debugf("looking for: %s", execFile)
114
if filepath.IsAbs(execFile) {
118
dir, file := filepath.Split(execFile)
120
// Now we have two possibilities:
121
// file == path indicating that the PATH was searched
122
// dir != "" indicating that it is a relative path
125
path := os.Getenv("PATH")
126
for _, name := range filepath.SplitList(path) {
127
result := filepath.Join(name, file)
128
info, err := os.Stat(result)
130
// Sanity check to see if executable.
131
if info.Mode()&0111 != 0 {
137
return "", fmt.Errorf("could not find %q in the path", file)
139
cwd, err := os.Getwd()
143
return filepath.Clean(filepath.Join(cwd, execFile)), nil
146
func copyExistingJujud(dir string) error {
147
// Assume that the user is running juju.
148
jujuLocation, err := findExecutable(os.Args[0])
150
logger.Infof("%v", err)
153
jujudLocation := filepath.Join(filepath.Dir(jujuLocation), "jujud")
154
logger.Debugf("checking: %s", jujudLocation)
155
info, err := os.Stat(jujudLocation)
157
logger.Infof("couldn't find existing jujud")
160
logger.Infof("found existing jujud")
161
// TODO(thumper): break this out into a util function.
162
// copy the file into the dir.
163
source, err := os.Open(jujudLocation)
165
logger.Infof("open source failed: %v", err)
169
target := filepath.Join(dir, "jujud")
170
logger.Infof("target: %v", target)
171
destination, err := os.OpenFile(target, os.O_RDWR|os.O_TRUNC|os.O_CREATE, info.Mode())
173
logger.Infof("open destination failed: %v", err)
176
defer destination.Close()
177
_, err = io.Copy(destination, source)
184
func buildJujud(dir string) error {
185
logger.Infof("building jujud")
117
186
cmds := [][]string{
118
187
{"go", "install", "launchpad.net/juju-core/cmd/jujud"},
119
188
{"strip", dir + "/jujud"},
125
194
out, err := cmd.CombinedOutput()
127
return version.Binary{}, fmt.Errorf("build command %q failed: %v; %s", args[0], err, out)
196
return fmt.Errorf("build command %q failed: %v; %s", args[0], err, out)
202
// bundleTools bundles all the current juju tools in gzipped tar
203
// format to the given writer.
204
// If forceVersion is not nil, a FORCE-VERSION file is included in
205
// the tools bundle so it will lie about its current version number.
206
func bundleTools(w io.Writer, forceVersion *version.Number) (version.Binary, error) {
207
dir, err := ioutil.TempDir("", "juju-tools")
209
return version.Binary{}, err
211
defer os.RemoveAll(dir)
213
if err := copyExistingJujud(dir); err != nil {
214
logger.Debugf("copy existing failed: %v", err)
215
if err := buildJujud(dir); err != nil {
216
return version.Binary{}, err
130
220
if forceVersion != nil {
221
logger.Debugf("forcing version to %s", forceVersion)
131
222
if err := ioutil.WriteFile(filepath.Join(dir, "FORCE-VERSION"), []byte(forceVersion.String()), 0666); err != nil {
132
223
return version.Binary{}, err