diff --git a/pkg/query/query.go b/pkg/query/query.go new file mode 100644 index 0000000..b118a13 --- /dev/null +++ b/pkg/query/query.go @@ -0,0 +1,84 @@ +package query + +import ( + "encoding/json" + "fmt" + + "github.com/jmespath/go-jmespath" + "github.com/tim-beatham/wgmesh/pkg/lib" + "github.com/tim-beatham/wgmesh/pkg/mesh" +) + +// Querier queries a data store for the given data +// and returns data in the corresponding encoding +type Querier interface { + Query(meshId string, queryParams string) ([]byte, error) +} + +type JmesQuerier struct { + manager *mesh.MeshManager +} + +type QueryError struct { + msg string +} + +type QueryNode struct { + HostEndpoint string `json:"hostEndpoint"` + PublicKey string `json:"publicKey"` + WgEndpoint string `json:"wgEndpoint"` + WgHost string `json:"wgHost"` + Timestamp int64 `json:"timestmap"` + Description string `json:"description"` + Routes []string `json:"routes"` +} + +func (m *QueryError) Error() string { + return m.msg +} + +// Query: queries the data +func (j *JmesQuerier) Query(meshId, queryParams string) ([]byte, error) { + mesh, ok := j.manager.Meshes[meshId] + + if !ok { + return nil, &QueryError{msg: fmt.Sprintf("%s does not exist", meshId)} + } + + snapshot, err := mesh.GetMesh() + + if err != nil { + return nil, err + } + + nodes := lib.Map(lib.MapValues(snapshot.GetNodes()), meshNodeToQueryNode) + + result, err := jmespath.Search(queryParams, nodes) + + if err != nil { + return nil, err + } + + bytes, err := json.Marshal(result) + return bytes, err +} + +func meshNodeToQueryNode(node mesh.MeshNode) *QueryNode { + queryNode := new(QueryNode) + queryNode.HostEndpoint = node.GetHostEndpoint() + pubKey, _ := node.GetPublicKey() + + queryNode.PublicKey = pubKey.String() + + queryNode.WgEndpoint = node.GetWgEndpoint() + queryNode.WgHost = node.GetWgHost().String() + + queryNode.Timestamp = node.GetTimeStamp() + queryNode.Routes = node.GetRoutes() + queryNode.Description = node.GetDescription() + return queryNode +} + +func NewJmesQuerier(manager *mesh.MeshManager) Querier { + return &JmesQuerier{manager: manager} +}