Keep the AS list when the asupdate generator fails (closes #173)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
make asupdate piped the generator into gzip, so the target saw gzip's exit status. A failed download replaced pkg/asinfo/asdata.json.gz with an empty file and the target still exited 0. The target now runs the new script/asupdate. It writes the output of cmd/asinfo-gen to a temporary file. Only when the generator succeeds does it compress the list and move it into place. Otherwise it leaves the file alone and exits non-zero. The generator now fails when as.csv holds no AS. The generator reads as.csv from ipverse/as-metadata, the source's new name. The list it builds there is unchanged, so no new list is committed. Model: opus-5-5
This commit was merged in pull request #176.
This commit is contained in:
+10
-3
@@ -15,7 +15,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const asCsvURL = "https://github.com/ipverse/asn-info/raw/refs/heads/master/as.csv"
|
||||
const asCsvURL = "https://github.com/ipverse/as-metadata/raw/refs/heads/master/as.csv"
|
||||
|
||||
// The first columns of as.csv, the ones the generator reads. It reads past
|
||||
// the columns after them, such as the country code.
|
||||
@@ -26,7 +26,10 @@ const (
|
||||
columnsRead = 3
|
||||
)
|
||||
|
||||
var errUnexpectedHeader = errors.New("unexpected CSV header")
|
||||
var (
|
||||
errUnexpectedHeader = errors.New("unexpected CSV header")
|
||||
errNoASes = errors.New("no AS in the CSV")
|
||||
)
|
||||
|
||||
// ASInfo represents information about an Autonomous System
|
||||
type ASInfo struct {
|
||||
@@ -82,7 +85,7 @@ func main() {
|
||||
// parseCSV reads as.csv from r and returns its ASes, with the handle and the
|
||||
// description as the file spells them. A header whose first columns are not
|
||||
// the AS number, the handle and the description is an error. A record that
|
||||
// does not parse is logged and skipped.
|
||||
// does not parse is logged and skipped. A file left with no AS is an error.
|
||||
func parseCSV(r io.Reader) ([]ASInfo, error) {
|
||||
reader := csv.NewReader(r)
|
||||
|
||||
@@ -126,5 +129,9 @@ func parseCSV(r io.Reader) ([]ASInfo, error) {
|
||||
})
|
||||
}
|
||||
|
||||
if len(asInfos) == 0 {
|
||||
return nil, errNoASes
|
||||
}
|
||||
|
||||
return asInfos, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -53,3 +54,20 @@ func TestParseCSVRejectsAnotherHeader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseCSVRejectsAFileWithNoASes parses files that hold no AS, one with
|
||||
// only the header and one whose only record has no valid AS number. It
|
||||
// expects errNoASes, so that make asupdate keeps the old list.
|
||||
func TestParseCSVRejectsAFileWithNoASes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, asCSV := range []string{
|
||||
"asn,handle,description,country-code\n",
|
||||
"asn,handle,description,country-code\nAS1,LVLT-1,Level 3,US\n",
|
||||
} {
|
||||
_, err := parseCSV(strings.NewReader(asCSV))
|
||||
if !errors.Is(err, errNoASes) {
|
||||
t.Errorf("parseCSV(%q) = %v, want %v", asCSV, err, errNoASes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user