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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
defer r.Body.Close()
|
||||
s := ctx.Value("versionStore")
|
||||
|
|
@ -84,7 +84,7 @@ func UpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request)
|
|||
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 {
|
||||
s := ctx.Value("versionStore")
|
||||
store, ok := s.(*storage.MySQLStorage)
|
||||
|
|
@ -120,3 +120,28 @@ func GetHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) *er
|
|||
w.Write(data)
|
||||
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
|
||||
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("DELETE").Path("/v2/{imageName:.*}/_trust/tuf/").Handler(hand(handlers.DeleteHandler, "push", "pull"))
|
||||
|
||||
svr := NewHTTPServer(
|
||||
http.Server{
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ import (
|
|||
// The database table must look like:
|
||||
// CREATE TABLE `tuf_files` (
|
||||
// `id` INT AUTO_INCREMENT,
|
||||
// `qdn` VARCHAR(255) NOT NULL
|
||||
// `gun` VARCHAR(255) NOT NULL
|
||||
// `role` VARCHAR(255) NOT NULL
|
||||
// `version` INT
|
||||
// `data` LONGBLOB
|
||||
// PRIMARY KEY (`id`)
|
||||
// UNIQUE INDEX (`qdn`, `role`, `version`)
|
||||
// UNIQUE INDEX (`gun`, `role`, `version`)
|
||||
// ) DEFAULT CHARSET=utf8;
|
||||
type MySQLStorage struct {
|
||||
sql.DB
|
||||
|
|
@ -28,25 +28,25 @@ func NewMySQLStorage(db *sql.DB) *MySQLStorage {
|
|||
|
||||
// Update multiple TUF records in a single transaction.
|
||||
// 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 {
|
||||
checkStmt := "SELECT count(*) FROM `tuf_files` WHERE `qdn`=? AND `role`=? AND `version`>=?;"
|
||||
insertStmt := "INSERT INTO `tuf_files` (`qdn`, `role`, `version`, `data`) VALUES (?,?,?,?) ;"
|
||||
func (db *MySQLStorage) UpdateCurrent(gun, role string, version int, data []byte) error {
|
||||
checkStmt := "SELECT count(*) FROM `tuf_files` WHERE `gun`=? AND `role`=? AND `version`>=?;"
|
||||
insertStmt := "INSERT INTO `tuf_files` (`gun`, `role`, `version`, `data`) VALUES (?,?,?,?) ;"
|
||||
|
||||
// ensure immediately previous version exists
|
||||
row := vdb.QueryRow(checkStmt, qdn, role, version)
|
||||
row := db.QueryRow(checkStmt, gun, role, version)
|
||||
var exists int
|
||||
err := row.Scan(&exists)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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.
|
||||
// That's OK, we're doing first write wins. The client will be messaged it
|
||||
// needs to rebase.
|
||||
_, err = vdb.Exec(insertStmt, qdn, role, version, data)
|
||||
_, err = db.Exec(insertStmt, gun, role, version, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -54,14 +54,14 @@ func (vdb *MySQLStorage) UpdateCurrent(qdn, role string, version int, data []byt
|
|||
}
|
||||
|
||||
// Get a specific TUF record
|
||||
func (vdb *MySQLStorage) GetCurrent(qdn, tufRole string) (data []byte, err error) {
|
||||
stmt := "SELECT `data` FROM `tuf_files` WHERE `qdn`=? AND `role`=? ORDER BY `version` DESC LIMIT 1;"
|
||||
rows, err := vdb.Query(stmt, qdn, tufRole) // this should be a QueryRow()
|
||||
func (db *MySQLStorage) GetCurrent(gun, tufRole string) (data []byte, err error) {
|
||||
stmt := "SELECT `data` FROM `tuf_files` WHERE `gun`=? AND `role`=? ORDER BY `version` DESC LIMIT 1;"
|
||||
rows, err := db.Query(stmt, gun, tufRole) // this should be a QueryRow()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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() {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -72,3 +72,9 @@ func (vdb *MySQLStorage) GetCurrent(qdn, tufRole string) (data []byte, err error
|
|||
}
|
||||
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