This repository has been archived by the owner on Jul 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
machine.go
113 lines (103 loc) · 3.51 KB
/
machine.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package cloudfuncs
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"cloud.google.com/go/firestore"
"github.com/juju/errors"
"google.golang.org/api/iterator"
)
const pathToMachinesInFirestore = "machines"
type Machine struct {
Name string `json:"name,omitempty" firestore:"name,omitempty"`
Power int `json:"power,omitempty" firestore:"power,omitempty"`
}
// MachineHttp is an HTTP Cloud Function that CRUDs a Machine document in the firestore
func MachineHttp(w http.ResponseWriter, r *http.Request) {
//todo: parse url to figure out what this is being called with so we know what we should do
// equivalent of api/machines/ -> get all, post all, delete all, batch update
// maybe get all with query methods filters?
// api/machines/$name -> get/add/update/delete specific machine
switch r.Method {
case http.MethodGet:
handleMachineHttpGet(w, r)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
_, err := fmt.Fprintf(w, "%s method not currently supported", r.Method)
if err != nil {
http.Error(w, "Error printing error", http.StatusInternalServerError)
log.Printf("fmt.Fprintf( method not currently supported): %v", err)
return
}
return
}
}
//do all the http stuff
func handleMachineHttpGet(w http.ResponseWriter, r *http.Request) {
client = getClient(w)
if client == nil {
http.Error(w, "Error connecting to firestore", http.StatusInternalServerError)
log.Printf("Error connecting to firestore")
return
}
machines, err := getAllMachines(r.Context(), client)
if err != nil {
http.Error(w, "Error locating machine data", http.StatusInternalServerError)
log.Printf("getAllMachines(): %v", err)
return
}
jsonData, _ := json.MarshalIndent(machines, "", " ")
_, err = fmt.Fprintln(w, string(jsonData))
if err != nil {
http.Error(w, "Error printing machine data", http.StatusInternalServerError)
log.Printf("fmt.Fprintln(w, string(jsonData))): %v", err)
return
}
}
//getAllMachines returns all machines in the firestore
func getAllMachines(ctx context.Context, client *firestore.Client) (machines []Machine, err error) {
iter := client.Collection(pathToMachinesInFirestore).Documents(ctx)
defer iter.Stop()
for {
var machine Machine
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
return machines, errors.Annotate(err, "iterator broke while loading all machine data from firestore.")
}
err = doc.DataTo(&machine)
if err != nil {
return machines, errors.Annotatef(err, "unable to parse specific machine's data: %v", doc.Data())
}
machines = append(machines, machine)
}
return
}
//getMachineByName returns a single machine with a matching name or an IsNotFound error if no such machine is in firestore
//we rely on the addMachine logic to ensure that there are no Machines with duplicate names
func getMachineByName(ctx context.Context, client *firestore.Client, name string) (machine Machine, err error) {
q := client.Collection(pathToMachinesInFirestore).Where("name", "==", name)
iter := q.Documents(ctx)
defer iter.Stop()
for {
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
return machine, errors.Annotate(err, "iterator broke while loading specific machine data from firestore.")
}
err = doc.DataTo(&machine)
if err != nil {
return machine, errors.Annotatef(err, "unable to parse specific machine's data: %v", doc.Data())
}
//assume no multiple results from firestore so no need to loop again
return machine, err
}
err = errors.NotFoundf("No machine with name %v", name)
return
}