package main import ( "bufio" "encoding/json" "fmt" "html/template" "io/ioutil" "net/http" "os" "regexp" "time" "github.com/sirupsen/logrus" ) // Build - Basic struct returned by zuul api in json format type Build struct { Status string `json:"result"` URL string `json:"log_url"` } type ParsedBuiltContainerLogLine struct { repository string tag string digest string } type ParsedBuiltContainerLogLines []*ParsedBuiltContainerLogLine func writeHTLMReport(success []string, failed []string, hash string, output string) { var reportTemplate = template.Must(template.New("report").Parse(`

Report latest containers

Latest hash: {{.Hash}}

Date: {{.Today.Format "01-02-2006 15:04"}}

Failing: {{.Failing}}

Passing: {{.Passing}}

{{range .Items}} {{ if eq .ContainerStatus "SUCCESS" }} {{ else }} {{ end }} {{end}}
Container Name Status
{{.ContainerName}} {{.ContainerStatus}}
`)) type Containers struct { ContainerName string ContainerStatus string } type Data struct { Items []*Containers Hash string Today time.Time Passing int Failing int } data := new(Data) data.Hash = hash data.Today = time.Now() data.Passing = len(success) data.Failing = len(failed) for _, container := range(success) { item := new(Containers) item.ContainerName = container item.ContainerStatus = "SUCCESS" data.Items = append(data.Items, item) } for _, container := range(failed) { item := new(Containers) item.ContainerName = container item.ContainerStatus = "FAILURE" data.Items = append(data.Items, item) } file, err := os.Create(output) if err != nil { logrus.Errorln("Failed to create HTML report file") } writer := bufio.NewWriter(file) if err := reportTemplate.Execute(writer, data); err != nil { writer.Flush() logrus.Fatal(err) } writer.Flush() } func getLatestGoodBuildURL(jobName string, opts *globalOptions) string { url := fmt.Sprintf("%sbuilds?job_name=%s", opts.zuulAPI, jobName) response, err := http.Get(url) var builds []Build if err != nil { logrus.Errorln("The HTTP request failed with error ", err) } else { data, _ := ioutil.ReadAll(response.Body) if err := json.Unmarshal(data, &builds); err != nil { logrus.Errorln("The unmarshal failed with error ", err) } } for _, build := range builds { if build.Status == "SUCCESS" { return build.URL } } return "" } func _fetch_(URL string) (string, error) { request, err := http.NewRequest(http.MethodGet, URL, nil) if err != nil { logrus.Errorln("The HTTP request failed with error ", err) return "", err } client := &http.Client{} response, err := client.Do(request) if err != nil { logrus.Errorln("Failed to get response from the HTTP request") return "", err } if response.StatusCode == 404 { msg := fmt.Sprintf("URL %s not found", URL) logrus.Errorln(msg) return "", fmt.Errorf(msg) } data, err := ioutil.ReadAll(response.Body) if err != nil { logrus.Errorln("Failed to read Body content") return "", err } return string(data), nil } func _fetch(URL string) (string, error) { response, err := http.Get(URL) if err != nil { logrus.Errorln("The HTTP request failed with error ", err) return "", err } if response.StatusCode == 404 { msg := fmt.Sprintf("URL not found: %s", URL) logrus.Errorln(msg) return "", fmt.Errorf(msg) } data, err := ioutil.ReadAll(response.Body) if err != nil { logrus.Errorln("Failed to read Body content") return "", err } return string(data), nil } func fetchLogs(URL string) string { // There are three different places where we can get the list of // containers... path := fmt.Sprintf("%slogs/containers-successfully-built.log", URL) data, _ := _fetch(path) if data == "" { path = fmt.Sprintf("%slogs/containers-built.log", URL) data , _ = _fetch(path) } if data == "" { path = fmt.Sprintf("%sci-framework-data/logs/containers-built.log", URL) data , _ = _fetch(path) } if data == "" { path = fmt.Sprintf("%sjob-output.txt", URL) data, _ = _fetch(path) } logrus.Info("Fetching logs in ", path) return data } func repoExists(repoName string, repositories []Container) bool { for _, container := range repositories { if container.Name == repoName { return true } } return false } func getCurrentTripleoRepo(api string) string { type DlrnApiResponse struct { PromoteName string `json:"promote_name"` RepoHash string `json:"repo_hash"` AggregateHash string `json:"aggregate_hash"` CommitHash string `json:"commit_hash"` } var returnApi []DlrnApiResponse apiEndpoint := "api/promotions?promote_name=current-tripleo&limit=1" apiUrl := fmt.Sprintf("%s/%s", api, apiEndpoint) response, err := http.Get(apiUrl) if err != nil { logrus.Errorln("The HTTP request failed with error ", err) } else { data, _ := ioutil.ReadAll(response.Body) if err := json.Unmarshal(data, &returnApi); err != nil { logrus.Errorln("The unmarshal failed with error ", err) } } if len(returnApi) > 0 { if returnApi[0].AggregateHash != "" { return returnApi[0].AggregateHash } return returnApi[0].RepoHash } return "" } func parseLog(data string) ParsedBuiltContainerLogLines { var parsedLogLines ParsedBuiltContainerLogLines r, _ := regexp.Compile(`(?m)\/([\w-]+)\s+([\w_]+)\s+([\w]+)`) for _, matches := range r.FindAllStringSubmatch(data, -1) { parsedLogLines = append(parsedLogLines, &ParsedBuiltContainerLogLine{ repository: matches[1], tag: matches[2], digest: matches[3], }) } return parsedLogLines }