add a tool to check the status of a TUF server (#8428)

Motivation: I often find myself digging through the XML in https://tuf.fleetctl.com to see if/when/what packages have been published in the different release channels, this tool aims to make the process less painful.

```
~/fleet $ go run tools/tuf/status/status.go --help
This is a CLI utility to fetch and filter the entries posted by a TUF repository.
  -key-filter string
    	filter keys using a regular expression (default "stable")
  -url string
    	URL of the TUF repository (default "https://tuf.fleetctl.com")
```

### Examples

- To filter all items on the edge channel use `--key-filter="edge"`
- To filter all items on version `1.3` including patches that run on Linux use `--key-filter="linux/1.3.*"`
- To filter Fleet Desktop items on `1.3.*`, `stable` and `edge` that run on macOS use `--key-filter="desktop/*.*/macos/(1.3.*|stable|edge)"`

### Example output

```
~/fleet $ go run tools/tuf/status/status.go --key-filter="desktop/*.*/macos/(1.3.*|stable|edge)"

Results filtered by "desktop/*.*/macos/(1.3.*|stable|edge)" and sorted by version, platform and key.

VERSION	PLATFORM	KEY                                            	LAST MODIFIED           	SIZE   	ETAG
1.3    	macos   	targets/desktop/macos/1.3/desktop.app.tar.gz   	2022-10-20T00:42:58.000Z	28.4 MB	"ceb7a975880db6ab9aea7907915406e3-4"	
1.3.0  	macos   	targets/desktop/macos/1.3.0/desktop.app.tar.gz 	2022-10-20T00:42:58.000Z	28.4 MB	"ceb7a975880db6ab9aea7907915406e3-4"	
1.3.1  	macos   	targets/desktop/macos/1.3.1/desktop.app.tar.gz 	2022-10-21T20:28:24.000Z	28.5 MB	"3c6641a0df00009f3f076bd6b4fbc748-4"	
edge   	macos   	targets/desktop/macos/edge/desktop.app.tar.gz  	2022-10-21T20:28:37.000Z	28.5 MB	"3c6641a0df00009f3f076bd6b4fbc748-4"	
stable 	macos   	targets/desktop/macos/stable/desktop.app.tar.gz	2022-10-20T00:43:06.000Z	28.4 MB	"ceb7a975880db6ab9aea7907915406e3-4"	
```
This commit is contained in:
Roberto Dip 2022-10-24 17:20:06 -03:00 committed by GitHub
parent 566173c93c
commit 37233112b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 158 additions and 0 deletions

View File

@ -0,0 +1,19 @@
# TUF status
```
~/fleet $ go run tools/tuf/status/status.go --help
This is a CLI utility to fetch and filter the entries posted by a TUF repository.
-key-filter string
filter keys using a regular expression (default "stable")
-url string
URL of the TUF repository (default "https://tuf.fleetctl.com")
Examples
- To filter all items on the edge channel use --key-filter="edge"
- To filter all items on version 1.3 including patches that run on Linux use --key-filter="linux/1.3.*"
- To filter Fleet Desktop items on 1.3.*, stable and edge that run on macOS use --key-filter="desktop/*.*/macos/(1.3.*|stable|edge)"
```

139
tools/tuf/status/status.go Normal file
View File

@ -0,0 +1,139 @@
package main
import (
"encoding/xml"
"flag"
"fmt"
"io"
"net/http"
"os"
"regexp"
"sort"
"strings"
"github.com/olekukonko/tablewriter"
)
type listBucketResult struct {
XMLName xml.Name `xml:"ListBucketResult"`
Text string `xml:",chardata"`
Xmlns string `xml:"xmlns,attr"`
Name string `xml:"Name"`
Prefix string `xml:"Prefix"`
Marker string `xml:"Marker"`
MaxKeys string `xml:"MaxKeys"`
IsTruncated string `xml:"IsTruncated"`
Contents []content `xml:"Contents"`
}
type content struct {
Text string `xml:",chardata"`
Key string `xml:"Key"`
LastModified string `xml:"LastModified"`
ETag string `xml:"ETag"`
Size int64 `xml:"Size"`
StorageClass string `xml:"StorageClass"`
}
func main() {
flag.CommandLine.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), `
This is a CLI utility to fetch and filter the entries posted by a TUF repository.
`)
flag.CommandLine.PrintDefaults()
fmt.Fprintf(flag.CommandLine.Output(), `
Examples
- To filter all items on the edge channel use --key-filter="edge"
- To filter all items on version 1.3 including patches that run on Linux use --key-filter="linux/1.3.*"
- To filter Fleet Desktop items on 1.3.*, stable and edge that run on macOS use --key-filter="desktop/*.*/macos/(1.3.*|stable|edge)"
`)
}
filter := flag.String("key-filter", "stable", "filter keys using a regular expression")
url := flag.String("url", "https://tuf.fleetctl.com", "URL of the TUF repository")
flag.Parse()
res, err := http.Get(*url)
if err != nil {
panic(err)
}
body, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
defer res.Body.Close()
var list listBucketResult
if err := xml.Unmarshal(body, &list); err != nil {
panic(err)
}
if err := printTable(list.Contents, *filter); err != nil {
panic(err)
}
}
func printTable(contents []content, filter string) error {
data := [][]string{}
regFilter, err := regexp.Compile(filter)
if err != nil {
return err
}
for _, content := range contents {
if regFilter.MatchString(content.Key) {
r := strings.Split(content.Key, "/")
platform, version := r[2], r[3]
data = append(data, []string{version, platform, content.Key, content.LastModified, byteCountSI(content.Size), content.ETag})
}
}
// sort by version, platform, key
sort.Slice(data, func(i, j int) bool {
if data[i][0] != data[j][0] {
return data[i][0] < data[j][0]
}
if data[i][1] != data[j][1] {
return data[i][1] < data[j][1]
}
return data[i][2] < data[j][2]
})
fmt.Printf("\nResults filtered by \"%s\" and sorted by version, platform and key.\n\n", filter)
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"version", "platform", "key", "last modified", "size", "etag"})
table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetTablePadding("\t")
table.SetNoWhiteSpace(true)
table.AppendBulk(data)
table.Render()
return nil
}
func byteCountSI(b int64) string {
const unit = 1000
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB",
float64(b)/float64(div), "kMGTPE"[exp])
}