github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/scripts/all_configs.go (about)

     1  // This program uses the Evergreen REST API to grab the most recent configuration
     2  // for each project and write each configuration file to the file system for
     3  // further analysis. This program's purpose is to provide a useful utility that's
     4  // too niche for the main CLI tool and provide a proof of concept to the REST API.
     5  //
     6  // Usage: upon execution, this program will load the user's CLI settings
     7  //   (default `~/.evergreen.yml`) and use them to download all project files
     8  //   to the working directory in the form of "<project_id>.yml"
     9  //
    10  // -c / --config can pass in a different CLI settings file
    11  //
    12  package main
    13  
    14  import (
    15  	"encoding/json"
    16  	"fmt"
    17  	"io"
    18  	"io/ioutil"
    19  	"net/http"
    20  
    21  	"github.com/evergreen-ci/evergreen/cli"
    22  	"github.com/jessevdk/go-flags"
    23  )
    24  
    25  // uiClient handles requests against the UI server.
    26  type uiClient struct {
    27  	client *http.Client
    28  	user   string
    29  	key    string
    30  	uiRoot string
    31  }
    32  
    33  // get executes a request against the given REST route, panicking on any errors.
    34  func (c *uiClient) get(route string) *http.Response {
    35  	url := c.uiRoot + "/rest/v1/" + route
    36  	req, err := http.NewRequest("GET", url, nil)
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  	req.Header.Add("Auth-Username", c.user)
    41  	req.Header.Add("Api-Key", c.key)
    42  	resp, err := c.client.Do(req)
    43  	if err != nil {
    44  		panic(err)
    45  	}
    46  	if resp.StatusCode != http.StatusOK {
    47  		panic(fmt.Sprintf("Bad Status (%v) : %v", url, resp.StatusCode))
    48  	}
    49  	return resp
    50  }
    51  
    52  // mustDecodeJSON is a quick helper for panicking if a Reader cannot be read as JSON.
    53  func mustDecodeJSON(r io.Reader, i interface{}) {
    54  	err := json.NewDecoder(r).Decode(i)
    55  	if err != nil {
    56  		panic(err)
    57  	}
    58  }
    59  
    60  // fetchAndWriteConfig downloads the most recent config for a project
    61  // and writes it to "project_name.yml" locally.
    62  func fetchAndWriteConfig(uic *uiClient, project string) {
    63  	fmt.Println("Downloading configuration for", project)
    64  	resp := uic.get("projects/" + project + "/versions")
    65  	v := struct {
    66  		Versions []struct {
    67  			Id string `json:"version_id"`
    68  		} `json:"versions"`
    69  	}{}
    70  	mustDecodeJSON(resp.Body, &v)
    71  	if len(v.Versions) == 0 {
    72  		fmt.Println("WARNING:", project, "has no versions")
    73  		return
    74  	}
    75  	resp = uic.get("versions/" + v.Versions[0].Id + "?config=1")
    76  	c := struct {
    77  		Config string `json:"config"`
    78  	}{}
    79  	mustDecodeJSON(resp.Body, &c)
    80  	if len(c.Config) == 0 {
    81  		fmt.Println("WARNING:", project, "has empty config file")
    82  		return
    83  	}
    84  	err := ioutil.WriteFile(project+".yml", []byte(c.Config), 0666)
    85  	if err != nil {
    86  		panic(err)
    87  	}
    88  }
    89  
    90  func main() {
    91  	opts := &cli.Options{}
    92  	var parser = flags.NewParser(opts, flags.Default)
    93  	_, err := parser.Parse()
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  	settings, err := cli.LoadSettings(opts)
    98  	if err != nil {
    99  		panic(err)
   100  	}
   101  	uic := &uiClient{
   102  		client: &http.Client{},
   103  		user:   settings.User,
   104  		key:    settings.APIKey,
   105  		uiRoot: settings.UIServerHost,
   106  	}
   107  
   108  	// fetch list of all projects
   109  	resp := uic.get("projects")
   110  	pList := struct {
   111  		Projects []string `json:"projects"`
   112  	}{}
   113  	mustDecodeJSON(resp.Body, &pList)
   114  
   115  	for _, p := range pList.Projects {
   116  		fetchAndWriteConfig(uic, p)
   117  	}
   118  }