~rogpeppe/juju-core/azure

« back to all changes in this revision

Viewing changes to environs/tools/build.go

  • Committer: Tarmac
  • Author(s): Tim Penhey
  • Date: 2013-07-17 01:59:54 UTC
  • mfrom: (1263.6.13 find-jujud)
  • Revision ID: tarmac-20130717015954-vbfukru18ysccfxq
[r=thumper] Use pre-built jujud if found.

Instead of rebuilding jujud everytime we want to upload some tools, try to
find jujud next to the juju being executed.

https://codereview.appspot.com/11326043/

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
        "fmt"
10
10
        "io"
11
11
        "io/ioutil"
12
 
        "launchpad.net/juju-core/version"
13
12
        "os"
14
13
        "os/exec"
15
14
        "path/filepath"
16
15
        "strings"
 
16
 
 
17
        "launchpad.net/loggo"
 
18
 
 
19
        "launchpad.net/juju-core/version"
17
20
)
18
21
 
 
22
var logger = loggo.GetLogger("juju.environs.tools")
 
23
 
19
24
// archive writes the executable files found in the given directory in
20
25
// gzipped tar format to w.  An error is returned if an entry inside dir
21
26
// is not a regular executable file.
33
38
 
34
39
        for _, ent := range entries {
35
40
                h := tarHeader(ent)
 
41
                logger.Debugf("adding entry: %#v", h)
36
42
                // ignore local umask
37
43
                if isExecutable(ent) {
38
44
                        h.Mode = 0755
103
109
        return append(env, val)
104
110
}
105
111
 
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")
112
 
        if err != nil {
113
 
                return version.Binary{}, err
114
 
        }
115
 
        defer os.RemoveAll(dir)
116
 
 
 
112
func findExecutable(execFile string) (string, error) {
 
113
        logger.Debugf("looking for: %s", execFile)
 
114
        if filepath.IsAbs(execFile) {
 
115
                return execFile, nil
 
116
        }
 
117
 
 
118
        dir, file := filepath.Split(execFile)
 
119
 
 
120
        // Now we have two possibilities:
 
121
        //   file == path indicating that the PATH was searched
 
122
        //   dir != "" indicating that it is a relative path
 
123
 
 
124
        if dir == "" {
 
125
                path := os.Getenv("PATH")
 
126
                for _, name := range filepath.SplitList(path) {
 
127
                        result := filepath.Join(name, file)
 
128
                        info, err := os.Stat(result)
 
129
                        if err == nil {
 
130
                                // Sanity check to see if executable.
 
131
                                if info.Mode()&0111 != 0 {
 
132
                                        return result, nil
 
133
                                }
 
134
                        }
 
135
                }
 
136
 
 
137
                return "", fmt.Errorf("could not find %q in the path", file)
 
138
        }
 
139
        cwd, err := os.Getwd()
 
140
        if err != nil {
 
141
                return "", err
 
142
        }
 
143
        return filepath.Clean(filepath.Join(cwd, execFile)), nil
 
144
}
 
145
 
 
146
func copyExistingJujud(dir string) error {
 
147
        // Assume that the user is running juju.
 
148
        jujuLocation, err := findExecutable(os.Args[0])
 
149
        if err != nil {
 
150
                logger.Infof("%v", err)
 
151
                return err
 
152
        }
 
153
        jujudLocation := filepath.Join(filepath.Dir(jujuLocation), "jujud")
 
154
        logger.Debugf("checking: %s", jujudLocation)
 
155
        info, err := os.Stat(jujudLocation)
 
156
        if err != nil {
 
157
                logger.Infof("couldn't find existing jujud")
 
158
                return err
 
159
        }
 
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)
 
164
        if err != nil {
 
165
                logger.Infof("open source failed: %v", err)
 
166
                return err
 
167
        }
 
168
        defer source.Close()
 
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())
 
172
        if err != nil {
 
173
                logger.Infof("open destination failed: %v", err)
 
174
                return err
 
175
        }
 
176
        defer destination.Close()
 
177
        _, err = io.Copy(destination, source)
 
178
        if err != nil {
 
179
                return err
 
180
        }
 
181
        return nil
 
182
}
 
183
 
 
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"},
124
193
                cmd.Env = env
125
194
                out, err := cmd.CombinedOutput()
126
195
                if err != nil {
127
 
                        return version.Binary{}, fmt.Errorf("build command %q failed: %v; %s", args[0], err, out)
128
 
                }
129
 
        }
 
196
                        return fmt.Errorf("build command %q failed: %v; %s", args[0], err, out)
 
197
                }
 
198
        }
 
199
        return nil
 
200
}
 
201
 
 
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")
 
208
        if err != nil {
 
209
                return version.Binary{}, err
 
210
        }
 
211
        defer os.RemoveAll(dir)
 
212
 
 
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
 
217
                }
 
218
        }
 
219
 
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
133
224
                }