Better semver handling

This commit is contained in:
James Hunt 2016-06-22 23:47:26 -04:00
parent 1c50779858
commit 2c856276ad
8 changed files with 206 additions and 12 deletions

View File

@ -59,6 +59,12 @@ The Genesis Index API strives to be simple and clean
GET /v1/release
```
## Get Latest Versions of All Tracked Releases
```
GET /v1/release/latest
```
## Get All Release Versions
```
@ -125,6 +131,12 @@ DELETE /v1/release/:name/v/:version
GET /v1/stemcell
```
## Get Latest Versions of All Tracked Stemcells
```
GET /v1/stemcell/latest
```
## Get All Stemcell Versions
```

View File

@ -36,6 +36,12 @@ func (api ReleaseAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
respond(w, err, 200, "success")
return
case match(r, `GET /v1/release/latest`):
log.Debugf("retrieving latest versions of all releases")
releases, err := FindLatestReleaseVersions(api.db)
respond(w, err, 200, releases)
return
case match(r, `GET /v1/release/[^/]+`):
name := extract(r, `/v1/release/([^/]+)$`)
log.Debugf("retrieving all versions of release '%s'", name)

View File

@ -36,6 +36,12 @@ func (api StemcellAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
respond(w, err, 200, "success")
return
case match(r, `GET /v1/stemcell/latest`):
log.Debugf("retrieving latest versions of all stemcells")
stemcells, err := FindLatestStemcellVersions(api.db)
respond(w, err, 200, stemcells)
return
case match(r, `GET /v1/stemcell/[^/]+`):
name := extract(r, `/v1/stemcell/([^/]+)$`)
log.Debugf("retrieving all versions of stemcell '%s'", name)

31
indexer
View File

@ -25,6 +25,7 @@ USAGE: $0 version (release|stemcell) NAME [VERSION]
$0 check (release|stemcell) NAME VERSION
$0 create (release|stemcell) NAME URL
$0 remove (release|stemcell) NAME [VERSION]
$0 latest (releases|stemcells)
$0 releases
$0 stemcells
$0 help
@ -177,6 +178,33 @@ cmd_show() {
exit 0
}
cmd_latest() {
local USAGE="latest (releases|stemcells)"
local type=$1 ; shift
if [[ -z $type || -n $1 ]]; then
echo >&2 "USAGE: $0 $USAGE"
exit 1
fi
case $type in
(release|releases)
curl --fail -Lsk -XGET ${GENESIS_INDEX}/v1/release/latest
exit $?
;;
(stemcell|stemcells)
curl --fail -Lsk -XGET ${GENESIS_INDEX}/v1/stemcell/latest
exit $?
;;
(*)
echo >&2 "unrecognized type '$type'"
echo >&2 "USAGE: $0 $USAGE"
exit 1
;;
esac
exit 0
}
cmd_list() {
local type=$1 ; shift
local USAGE="$type"
@ -227,6 +255,9 @@ main() {
(show)
cmd_show $*
;;
(latest)
cmd_latest $*
;;
(stemcells|releases)
cmd_list $command $*
;;

View File

@ -74,7 +74,7 @@ WHERE name = $1
AND valid = 1
ORDER BY
version DESC`, name)
vnum DESC`, name)
if err != nil {
return l, err
}
@ -98,6 +98,47 @@ ORDER BY
return l, nil
}
func FindLatestReleaseVersions(d *db.DB) ([]Release, error) {
l := make([]Release, 0)
r, err := d.Query(`
SELECT
v.name,
v.version,
v.sha1,
v.url
FROM
release_versions v
INNER JOIN (
SELECT
name,
MAX(vnum) AS latest
FROM release_versions
WHERE valid = 1
GROUP BY name
) q
ON
q.name = v.name
AND q.latest = v.vnum
`)
if err != nil {
return l, err
}
for r.Next() {
var o Release
if err = r.Scan(&o.Name, &o.Version, &o.SHA1, &o.URL); err != nil {
return l, err
}
l = append(l, o)
}
return l, nil
}
func FindReleaseVersion(d *db.DB, name, version string) (Release, error) {
var o Release
@ -111,9 +152,23 @@ func FindReleaseVersion(d *db.DB, name, version string) (Release, error) {
}
r, err := d.Query(fmt.Sprintf(`
SELECT name, version, sha1, url
FROM release_versions
WHERE name = $1 AND valid = 1 %s`, where), args...)
SELECT
name,
version,
sha1,
url
FROM
release_versions
WHERE name = $1
AND valid = 1
%s
ORDER BY
vnum DESC
LIMIT 1
`, where), args...)
if err != nil {
return o, err
}
@ -166,8 +221,11 @@ func CheckReleaseVersion(d *db.DB, name, version string) {
n, _ := d.Count(`SELECT * FROM release_versions WHERE name = $1 AND version = $2`, name, version)
if n == 0 {
recheck = false
err = d.Exec(`INSERT INTO release_versions (name, version, valid) VALUES ($1, $2, 0)`,
name, version)
num, err := vnum(version)
if err == nil {
d.Exec(`INSERT INTO release_versions (name, version, vnum, valid) VALUES ($1, $2, $3, 0)`,
name, version, num)
}
}
/* download and SHA1 the file */

View File

@ -41,6 +41,7 @@ func Database(driver, dsn string) (*db.DB, error) {
CREATE TABLE release_versions (
name VARCHAR(200) NOT NULL,
version VARCHAR(20) NOT NULL,
vnum INTEGER NOT NULL,
sha1 VARCHAR(200) NOT NULL DEFAULT '',
url TEXT NOT NULL DEFAULT '',
valid INTEGER NOT NULL DEFAULT 0,
@ -56,6 +57,7 @@ func Database(driver, dsn string) (*db.DB, error) {
CREATE TABLE stemcell_versions (
name VARCHAR(200) NOT NULL,
version VARCHAR(20) NOT NULL,
vnum INTEGER NOT NULL,
sha1 VARCHAR(200) NOT NULL DEFAULT '',
url TEXT NOT NULL DEFAULT '',
valid INTEGER NOT NULL DEFAULT 0,

View File

@ -74,7 +74,7 @@ WHERE name = $1
AND valid = 1
ORDER BY
version DESC`, name)
vnum DESC`, name)
if err != nil {
return l, err
}
@ -98,6 +98,47 @@ ORDER BY
return l, nil
}
func FindLatestStemcellVersions(d *db.DB) ([]Stemcell, error) {
l := make([]Stemcell, 0)
r, err := d.Query(`
SELECT
v.name,
v.version,
v.sha1,
v.url
FROM
stemcell_versions v
INNER JOIN (
SELECT
name,
MAX(vnum) AS latest
FROM stemcell_versions
WHERE valid = 1
GROUP BY name
) q
ON
q.name = v.name
AND q.latest = v.vnum
`)
if err != nil {
return l, err
}
for r.Next() {
var o Stemcell
if err = r.Scan(&o.Name, &o.Version, &o.SHA1, &o.URL); err != nil {
return l, err
}
l = append(l, o)
}
return l, nil
}
func FindStemcellVersion(d *db.DB, name, version string) (Stemcell, error) {
var o Stemcell
@ -111,9 +152,23 @@ func FindStemcellVersion(d *db.DB, name, version string) (Stemcell, error) {
}
r, err := d.Query(fmt.Sprintf(`
SELECT name, version, sha1, url
FROM stemcell_versions
WHERE name = $1 AND valid = 1 %s`, where), args...)
SELECT
name,
version,
sha1,
url
FROM
stemcell_versions
WHERE name = $1
AND valid = 1
%s
ORDER BY
vnum DESC
LIMIT 1
`, where), args...)
if err != nil {
return o, err
}
@ -166,8 +221,11 @@ func CheckStemcellVersion(d *db.DB, name, version string) {
n, _ := d.Count(`SELECT * FROM stemcell_versions WHERE name = $1 AND version = $2`, name, version)
if n == 0 {
recheck = false
err = d.Exec(`INSERT INTO stemcell_versions (name, version, valid) VALUES ($1, $2, 0)`,
name, version)
num, err := vnum(version)
if err == nil {
d.Exec(`INSERT INTO stemcell_versions (name, version, vnum, valid) VALUES ($1, $2, $3, 0)`,
name, version, num)
}
}
/* download and SHA1 the file */

21
util.go
View File

@ -8,6 +8,8 @@ import (
"net/http"
"os"
"regexp"
"strconv"
"strings"
"github.com/starkandwayne/goutils/log"
)
@ -104,3 +106,22 @@ func authed(w http.ResponseWriter, r *http.Request) bool {
w.WriteHeader(403)
return false
}
func vnum(v string) (uint64, error) {
sem := strings.Split(v, ".")
for len(sem) < 3 {
sem = append(sem, "0")
}
var n uint64 = 0
for i := 0; i < 3; i++ {
u, err := strconv.ParseUint(sem[i], 10, 64)
if err != nil {
log.Debugf("vnum had an issue with '%s': %s", v, err)
return n, err
}
n = n*1000 + u
}
return n, nil
}