From 0858d284bc4c3e313169095907149085ce681a81 Mon Sep 17 00:00:00 2001 From: Aaron Meihm Date: Thu, 11 Feb 2016 14:59:42 -0600 Subject: [PATCH] [medium] add functions to list target loader entries in manifest reader --- client/client.go | 39 ++++++++++++++++++++++ client/mig-console/manifest.go | 14 ++++++++ database/loader.go | 27 +++++++++++++++ loader.go | 6 ++-- mig-api/api.go | 1 + mig-api/manifest_endpoints.go | 61 ++++++++++++++++++++++++++++++++++ 6 files changed, 146 insertions(+), 2 deletions(-) diff --git a/client/client.go b/client/client.go index 1259d1f5..62e804dd 100644 --- a/client/client.go +++ b/client/client.go @@ -395,6 +395,28 @@ func (cli Client) GetManifestRecord(mid float64) (mr mig.ManifestRecord, err err return } +// Retrieve list of known loader entries that will match manifest mid +func (cli Client) GetManifestLoaders(mid float64) (ldrs []mig.LoaderEntry, err error) { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("GetManifestLoaders() -> %v", e) + } + }() + target := fmt.Sprintf("manifest/loaders/?manifestid=%.0f", mid) + resource, err := cli.GetAPIResource(target) + if err != nil { + panic(err) + } + if resource.Collection.Items[0].Data[0].Name != "loaders" { + panic("API returned something that is not a loader list... something's wrong.") + } + ldrs, err = ValueToLoaderEntries(resource.Collection.Items[0].Data[0].Value) + if err != nil { + panic(err) + } + return +} + // Change the status of an existing manifest record func (cli Client) ManifestRecordStatus(mr mig.ManifestRecord, status string) (err error) { defer func() { @@ -578,6 +600,23 @@ func ValueToAction(v interface{}) (a mig.Action, err error) { return } +func ValueToLoaderEntries(v interface{}) (l []mig.LoaderEntry, err error) { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("ValueToLoaderEntries() -> %v", e) + } + }() + bData, err := json.Marshal(v) + if err != nil { + panic(err) + } + err = json.Unmarshal(bData, &l) + if err != nil { + panic(err) + } + return +} + func ValueToManifestRecord(v interface{}) (m mig.ManifestRecord, err error) { defer func() { if e := recover(); e != nil { diff --git a/client/mig-console/manifest.go b/client/mig-console/manifest.go index df3d504a..b3f4f21f 100644 --- a/client/mig-console/manifest.go +++ b/client/mig-console/manifest.go @@ -91,6 +91,8 @@ exit exit this mode (also works with ctrl+d) json show json of manifest record stored in database +loaders show known loader entries that will match this manifest + r refresh the manifest (get latest version from database) reset reset manifest status (marks manifest as staged, removes signatures) @@ -112,6 +114,18 @@ sign add a signature to the manifest record panic(err) } fmt.Printf("%s\n", jsonmr) + case "loaders": + ldrs, err := cli.GetManifestLoaders(mid) + if err != nil { + panic(err) + } + for _, x := range ldrs { + buf, err := json.Marshal(x) + if err != nil { + panic(err) + } + fmt.Printf("%v\n", string(buf)) + } case "r": mr, err = cli.GetManifestRecord(mid) if err != nil { diff --git a/database/loader.go b/database/loader.go index c7313b6f..4f78b234 100644 --- a/database/loader.go +++ b/database/loader.go @@ -94,3 +94,30 @@ func (db *DB) ManifestIDFromLoaderID(lid float64) (ret float64, err error) { err = fmt.Errorf("No matching manifest was found for loader entry") return } + +// Return all the loader entries that match the targeting string for manifest mid +func (db *DB) AllLoadersFromManifestID(mid float64) (ret []mig.LoaderEntry, err error) { + var mtarg string + err = db.c.QueryRow(`SELECT target FROM manifests + WHERE status='active' AND id=$1`, mid).Scan(&mtarg) + if err != nil { + return + } + qs := fmt.Sprintf("SELECT id, loadername, name FROM loaders WHERE %v", mtarg) + rows, err := db.c.Query(qs) + if err != nil { + return + } + if rows != nil { + defer rows.Close() + } + for rows.Next() { + nle := mig.LoaderEntry{} + err = rows.Scan(&nle.ID, &nle.Name, &nle.AgentName) + if err != nil { + return ret, err + } + ret = append(ret, nle) + } + return +} diff --git a/loader.go b/loader.go index 063dee60..3300fde6 100644 --- a/loader.go +++ b/loader.go @@ -6,7 +6,9 @@ package mig /* import "mig.ninja/mig" */ +// Describes a loader entry stored in the database type LoaderEntry struct { - ID float64 - Name string + ID float64 // Loader ID + Name string // Loader name + AgentName string // Loader environment, agent name } diff --git a/mig-api/api.go b/mig-api/api.go index 7f8f68d9..a46862ca 100644 --- a/mig-api/api.go +++ b/mig-api/api.go @@ -81,6 +81,7 @@ func main() { s.HandleFunc("/manifest/sign/", authenticate(signManifest)).Methods("POST") s.HandleFunc("/manifest/status/", authenticate(statusManifest)).Methods("POST") s.HandleFunc("/manifest/new/", authenticate(newManifest)).Methods("POST") + s.HandleFunc("/manifest/loaders/", authenticate(manifestLoaders)).Methods("GET") s.HandleFunc("/search", authenticate(search)).Methods("GET") s.HandleFunc("/action", authenticate(getAction)).Methods("GET") s.HandleFunc("/action/create/", authenticate(describeCreateAction)).Methods("GET") diff --git a/mig-api/manifest_endpoints.go b/mig-api/manifest_endpoints.go index 02a27d19..da3f62b7 100644 --- a/mig-api/manifest_endpoints.go +++ b/mig-api/manifest_endpoints.go @@ -217,6 +217,59 @@ func getManifest(respWriter http.ResponseWriter, request *http.Request) { respond(200, resource, respWriter, request) } +// Given a manifest ID, return the list of known loaders which match the +// targeting string +func manifestLoaders(respWriter http.ResponseWriter, request *http.Request) { + loc := fmt.Sprintf("%s%s", ctx.Server.Host, request.URL.String()) + opid := getOpID(request) + resource := cljs.New(loc) + defer func() { + if e := recover(); e != nil { + ctx.Channels.Log <- mig.Log{OpID: opid, Desc: fmt.Sprintf("%v", e)}.Err() + resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: fmt.Sprintf("%v", e)}) + respond(500, resource, respWriter, request) + } + ctx.Channels.Log <- mig.Log{OpID: opid, Desc: "leaving manifestLoaders()"}.Debug() + }() + mid, err := strconv.ParseFloat(request.URL.Query()["manifestid"][0], 64) + if err != nil { + err = fmt.Errorf("Wrong parameters 'manifestid': '%v'", err) + panic(err) + } + + if mid > 0 { + _, err = ctx.DB.GetManifestFromID(mid) + if err != nil { + if fmt.Sprintf("%v", err) == "Error while retrieving manifest: 'sql: no rows in result set'" { + resource.SetError(cljs.Error{ + Code: fmt.Sprintf("%.0f", opid), + Message: fmt.Sprintf("Manifest ID '%.0f' not found", mid)}) + respond(404, resource, respWriter, request) + return + } else { + panic(err) + } + } + } else { + // bad request, return 400 + resource.SetError(cljs.Error{ + Code: fmt.Sprintf("%.0f", opid), + Message: fmt.Sprintf("Invalid Manifest ID '%.0f'", mid)}) + respond(400, resource, respWriter, request) + return + } + ldrs, err := ctx.DB.AllLoadersFromManifestID(mid) + if err != nil { + panic(err) + } + li, err := loaderEntrysToItem(ldrs, mid, ctx) + if err != nil { + panic(err) + } + resource.AddItem(li) + respond(200, resource, respWriter, request) +} + // API entry point used to request a file be sent to the loader from the API. // This would typically be called from a loader after it has received a // manifest and determined updates to file system objects are required. @@ -355,3 +408,11 @@ func manifestRecordToItem(mr mig.ManifestRecord, ctx Context) (item cljs.Item, e } return } + +func loaderEntrysToItem(ldrs []mig.LoaderEntry, mid float64, ctx Context) (item cljs.Item, err error) { + item.Href = fmt.Sprintf("%s/manifest/loaders?manifestid=%.0f", ctx.Server.BaseURL, mid) + item.Data = []cljs.Data{ + {Name: "loaders", Value: ldrs}, + } + return +}