Better semver handling
This commit is contained in:
parent
1c50779858
commit
2c856276ad
12
README.md
12
README.md
|
@ -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
|
||||
|
||||
```
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
31
indexer
|
@ -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 $*
|
||||
;;
|
||||
|
|
70
release.go
70
release.go
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
70
stemcell.go
70
stemcell.go
|
@ -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
21
util.go
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue