mirror of https://github.com/docker/docs.git
adding delete to server
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
b0ee6f0c4e
commit
0f1e8b0134
|
|
@ -33,7 +33,7 @@ func MainHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddHandler accepts urls in the form /<imagename>/<tag>
|
// AddHandler adds the provided json data for the role and GUN specified in the URL
|
||||||
func UpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
|
func UpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
s := ctx.Value("versionStore")
|
s := ctx.Value("versionStore")
|
||||||
|
|
@ -84,7 +84,7 @@ func UpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHandler accepts urls in the form /<imagename>/<tuf file>.json
|
// GetHandler returns the json for a specified role and GUN.
|
||||||
func GetHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
|
func GetHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
|
||||||
s := ctx.Value("versionStore")
|
s := ctx.Value("versionStore")
|
||||||
store, ok := s.(*storage.MySQLStorage)
|
store, ok := s.(*storage.MySQLStorage)
|
||||||
|
|
@ -120,3 +120,28 @@ func GetHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *er
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteHandler deletes all data for a GUN. A 200 responses indicates success.
|
||||||
|
func DeleteHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
|
||||||
|
s := ctx.Value("versionStore")
|
||||||
|
store, ok := s.(*storage.MySQLStorage)
|
||||||
|
if !ok {
|
||||||
|
return &errors.HTTPError{
|
||||||
|
HTTPStatus: http.StatusInternalServerError,
|
||||||
|
Code: 9999,
|
||||||
|
Err: fmt.Errorf("Version store not configured"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
gun := vars["imageName"]
|
||||||
|
err := store.Delete(gun)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("[Notary Server] 500 DELETE repository: %s", gun)
|
||||||
|
return &errors.HTTPError{
|
||||||
|
HTTPStatus: http.StatusInternalServerError,
|
||||||
|
Code: 9999,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ func run(ctx context.Context, addr, tlsCertFile, tlsKeyFile string, trust signed
|
||||||
// TODO (endophage): use correct regexes for image and tag names
|
// TODO (endophage): use correct regexes for image and tag names
|
||||||
r.Methods("GET").Path("/v2/{imageName:.*}/_trust/tuf/{tufRole:(root|targets|timestamp|snapshot)}.json").Handler(hand(handlers.GetHandler, "pull"))
|
r.Methods("GET").Path("/v2/{imageName:.*}/_trust/tuf/{tufRole:(root|targets|timestamp|snapshot)}.json").Handler(hand(handlers.GetHandler, "pull"))
|
||||||
r.Methods("POST").Path("/v2/{imageName:.*}/_trust/tuf/{tufRole:(root|targets|timestamp|snapshot)}.json").Handler(hand(handlers.UpdateHandler, "push", "pull"))
|
r.Methods("POST").Path("/v2/{imageName:.*}/_trust/tuf/{tufRole:(root|targets|timestamp|snapshot)}.json").Handler(hand(handlers.UpdateHandler, "push", "pull"))
|
||||||
|
r.Methods("DELETE").Path("/v2/{imageName:.*}/_trust/tuf/").Handler(hand(handlers.DeleteHandler, "push", "pull"))
|
||||||
|
|
||||||
svr := NewHTTPServer(
|
svr := NewHTTPServer(
|
||||||
http.Server{
|
http.Server{
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ import (
|
||||||
// The database table must look like:
|
// The database table must look like:
|
||||||
// CREATE TABLE `tuf_files` (
|
// CREATE TABLE `tuf_files` (
|
||||||
// `id` INT AUTO_INCREMENT,
|
// `id` INT AUTO_INCREMENT,
|
||||||
// `qdn` VARCHAR(255) NOT NULL
|
// `gun` VARCHAR(255) NOT NULL
|
||||||
// `role` VARCHAR(255) NOT NULL
|
// `role` VARCHAR(255) NOT NULL
|
||||||
// `version` INT
|
// `version` INT
|
||||||
// `data` LONGBLOB
|
// `data` LONGBLOB
|
||||||
// PRIMARY KEY (`id`)
|
// PRIMARY KEY (`id`)
|
||||||
// UNIQUE INDEX (`qdn`, `role`, `version`)
|
// UNIQUE INDEX (`gun`, `role`, `version`)
|
||||||
// ) DEFAULT CHARSET=utf8;
|
// ) DEFAULT CHARSET=utf8;
|
||||||
type MySQLStorage struct {
|
type MySQLStorage struct {
|
||||||
sql.DB
|
sql.DB
|
||||||
|
|
@ -28,25 +28,25 @@ func NewMySQLStorage(db *sql.DB) *MySQLStorage {
|
||||||
|
|
||||||
// Update multiple TUF records in a single transaction.
|
// Update multiple TUF records in a single transaction.
|
||||||
// Always insert a new row. The unique constraint will ensure there is only ever
|
// Always insert a new row. The unique constraint will ensure there is only ever
|
||||||
func (vdb *MySQLStorage) UpdateCurrent(qdn, role string, version int, data []byte) error {
|
func (db *MySQLStorage) UpdateCurrent(gun, role string, version int, data []byte) error {
|
||||||
checkStmt := "SELECT count(*) FROM `tuf_files` WHERE `qdn`=? AND `role`=? AND `version`>=?;"
|
checkStmt := "SELECT count(*) FROM `tuf_files` WHERE `gun`=? AND `role`=? AND `version`>=?;"
|
||||||
insertStmt := "INSERT INTO `tuf_files` (`qdn`, `role`, `version`, `data`) VALUES (?,?,?,?) ;"
|
insertStmt := "INSERT INTO `tuf_files` (`gun`, `role`, `version`, `data`) VALUES (?,?,?,?) ;"
|
||||||
|
|
||||||
// ensure immediately previous version exists
|
// ensure immediately previous version exists
|
||||||
row := vdb.QueryRow(checkStmt, qdn, role, version)
|
row := db.QueryRow(checkStmt, gun, role, version)
|
||||||
var exists int
|
var exists int
|
||||||
err := row.Scan(&exists)
|
err := row.Scan(&exists)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if exists != 0 {
|
if exists != 0 {
|
||||||
return fmt.Errorf("Attempting to write an old version for QDN: %s, role: %s, version: %d. A newer version is available.", qdn, role, version)
|
return fmt.Errorf("Attempting to write an old version for gun: %s, role: %s, version: %d. A newer version is available.", gun, role, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
// attempt to insert. Due to race conditions with the check this could fail.
|
// attempt to insert. Due to race conditions with the check this could fail.
|
||||||
// That's OK, we're doing first write wins. The client will be messaged it
|
// That's OK, we're doing first write wins. The client will be messaged it
|
||||||
// needs to rebase.
|
// needs to rebase.
|
||||||
_, err = vdb.Exec(insertStmt, qdn, role, version, data)
|
_, err = db.Exec(insertStmt, gun, role, version, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -54,14 +54,14 @@ func (vdb *MySQLStorage) UpdateCurrent(qdn, role string, version int, data []byt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a specific TUF record
|
// Get a specific TUF record
|
||||||
func (vdb *MySQLStorage) GetCurrent(qdn, tufRole string) (data []byte, err error) {
|
func (db *MySQLStorage) GetCurrent(gun, tufRole string) (data []byte, err error) {
|
||||||
stmt := "SELECT `data` FROM `tuf_files` WHERE `qdn`=? AND `role`=? ORDER BY `version` DESC LIMIT 1;"
|
stmt := "SELECT `data` FROM `tuf_files` WHERE `gun`=? AND `role`=? ORDER BY `version` DESC LIMIT 1;"
|
||||||
rows, err := vdb.Query(stmt, qdn, tufRole) // this should be a QueryRow()
|
rows, err := db.Query(stmt, gun, tufRole) // this should be a QueryRow()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
// unique constraint on (qdn, role) will ensure only one row is returned (or none if no match is found)
|
// unique constraint on (gun, role) will ensure only one row is returned (or none if no match is found)
|
||||||
if !rows.Next() {
|
if !rows.Next() {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -72,3 +72,9 @@ func (vdb *MySQLStorage) GetCurrent(qdn, tufRole string) (data []byte, err error
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *MySQLStorage) Delete(gun string) error {
|
||||||
|
stmt := "DELETE FROM `tuf_files` WHERE `gun`=?;"
|
||||||
|
_, err := db.Exec(stmt, gun)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue