diff --git a/CHANGELOG b/CHANGELOG index 332314063..9118f0f06 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -34,3 +34,6 @@ 0.9.0 / 2017-11-22 * Kubernetes support + +0.9.1 / 2017-12-01 + * Support output to a URL. This will do a form post to the provided callback URL. diff --git a/pkg/bundle/generate.go b/pkg/bundle/generate.go index 13fe503d7..1952b0e73 100644 --- a/pkg/bundle/generate.go +++ b/pkg/bundle/generate.go @@ -1,9 +1,14 @@ package bundle import ( + "bytes" "context" "encoding/json" + "io" "io/ioutil" + "mime/multipart" + "net/http" + "net/url" "os" "path/filepath" "time" @@ -16,6 +21,14 @@ import ( // Generate a new support bundle and write the results as an archive at pathname func Generate(tasks []types.Task, timeout time.Duration, pathname string) error { + var isURL bool + + callbackURL, err := url.Parse(pathname) + if err == nil && (callbackURL.Scheme == "http" || callbackURL.Scheme == "https") { + isURL = true + pathname = "/tmp/bundle.tar.gz" + } + collectDir, err := ioutil.TempDir(filepath.Dir(pathname), "") if err != nil { return errors.Wrap(err, "Creating a temporary directory to store results failed") @@ -57,9 +70,44 @@ func Generate(tasks []types.Task, timeout time.Duration, pathname string) error comp := compressor.NewTgz() comp.SetTarConfig(compressor.Tar{TruncateLongFiles: true}) // trailing slash keeps the parent directory from being included in archive + if err := comp.Compress(collectDir+"/", pathname); err != nil { return errors.Wrap(err, "Compressing results directory failed") } + if isURL { + var b bytes.Buffer + w := multipart.NewWriter(&b) + + file, err := os.Open(pathname) + if err != nil { + return errors.Wrap(err, "finding the file that was just compressed") + } + defer file.Close() + fw, err := w.CreateFormFile("file", pathname) + if err != nil { + return errors.Wrap(err, "creating multipart form") + } + + if _, err = io.Copy(fw, file); err != nil { + return errors.Wrap(err, "copying buffer") + } + + w.Close() + + req, err := http.NewRequest("POST", callbackURL.String(), &b) + if err != nil { + return errors.Wrap(err, "making request") + } + + req.Header.Set("Content-Type", w.FormDataContentType()) + + client := &http.Client{} + _, err = client.Do(req) + if err != nil { + return errors.Wrap(err, "completing request") + } + } + return nil }