Implement initial version of fetch_artifact
BUG=121042212
Change-Id: Ib6a701df8c28decd48771c65ca9f618c8d0cf8fe
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..466e248
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+out/
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e23d01b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,31 @@
+# Fetch Artifact
+
+Fetch artifact is a tool for downloading artifacts from Android's continuous integration service.
+
+
+## Options
+
+* `target`: **Required** - The target you would like to download the artifact from.
+* `build_id`: **Required** - The build_id of the target to download the artifact from.
+* `artifact`: **Required** - The artifact to download.
+* `output`: *Optional* - If you would like the contents of the file to be written to a specific file
+* `-`: *Optional* - If you would like the contents of the file to be written to stdout (must be the last arg)
+
+
+## Example useage
+
+```
+fetch_artifact -target=aosp_arm64-userdebug -build_id=7000390 -artifact=COPIED
+```
+
+### Streaming contents to stdout
+
+```
+fetch_artifact -target=aosp_arm64-userdebug -build_id=7000390 -artifact=COPIED -
+```
+
+## Development
+
+### Building
+
+OUT_DIR=out ./build
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..2040428
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -ex
+
+# Copyright 2020 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+OUT=${OUT_DIR:-out} # default to out if not set.
+../prebuilts/go/linux-x86/bin/go build -o ${OUT}/fetch_artifact fetch_artifact.go
diff --git a/fetch_artifact.go b/fetch_artifact.go
new file mode 100644
index 0000000..843864c
--- /dev/null
+++ b/fetch_artifact.go
@@ -0,0 +1,96 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path"
+)
+
+var target = flag.String("target", "", "the target to fetch from")
+var buildID = flag.String("build_id", "", "the build id to fetch from")
+var artifact = flag.String("artifact", "", "the artifact to download")
+var output = flag.String("output", "", "the file name to save as")
+var writeToStdout = false
+
+func errPrint(msg string) {
+ fmt.Fprintln(os.Stderr, msg)
+ os.Exit(1)
+}
+
+func main() {
+ flag.Parse()
+ args := flag.Args()
+ // We only support passing 1 argument `-` so if we have more than
+ // one argument this is an error state,
+ if len(args) > 1 {
+ errPrint("Error: Too many arguments passed to fetch_artifact.")
+ }
+
+ if len(args) > 0 {
+ writeToStdout = args[len(args)-1] == "-"
+ if !writeToStdout {
+ errPrint(fmt.Sprintf(
+ "Error: Only supported final argument to fetch_artifact is `-` but got `%s`.", args[len(args)-1]))
+ }
+
+ if len(*output) > 0 && writeToStdout {
+ errPrint("Error: Both '-output' and '-' flags can not be used together.")
+ }
+ }
+
+ url := fmt.Sprintf("https://androidbuildinternal.googleapis.com/android/internal/build/v3/builds/%s/%s/attempts/latest/artifacts/%s/url", *buildID, *target, *artifact)
+
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ errPrint(fmt.Sprintf("unable to build request %v", err))
+ }
+ req.Header.Set("Accept", "application/json")
+
+ client := http.Client{}
+ res, err := client.Do(req)
+ if err != nil {
+ errPrint(fmt.Sprintf("Unable to make request %s.", err))
+ }
+ defer res.Body.Close()
+
+ if res.Status != "200 OK" {
+ body, _ := ioutil.ReadAll(res.Body)
+ errPrint(fmt.Sprintf("Unable to download artifact: %s\n %s.", res.Status, body))
+ }
+
+ if writeToStdout {
+ io.Copy(os.Stdout, res.Body)
+ return
+ }
+
+ fileName := *artifact
+ if len(*output) > 0 {
+ fileName = *output
+ }
+
+ f, err := os.Create(path.Base(fileName))
+ if err != nil {
+ errPrint(fmt.Sprintf("Unable to create file %s.", err))
+ }
+ defer f.Close()
+ io.Copy(f, res.Body)
+ fmt.Printf("File %s created.\n", f.Name())
+}