/
main.go
280 lines (228 loc) · 7.02 KB
/
main.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
package main
import (
"bufio"
"context"
"log"
"net"
"os"
"strings"
"time"
pb "github.com/nazufel/wizter/wizard"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
"google.golang.org/grpc"
)
const configMapFile = "./wizards-server-configMap.txt"
type server struct {
pb.WizardServiceServer
}
func main() {
log.Println("starting wizards server")
// set envs for local dev if the intercept env file exists
log.Printf("checking for configMap file at: %v", configMapFile)
_, err := os.Stat(configMapFile)
if !os.IsNotExist(err) {
log.Printf("found %s file. setting environment variables", configMapFile)
loadConfigs()
}
if os.IsNotExist(err) {
log.Printf("did not find config file: %s. using Kubernetes environment", configMapFile)
}
log.Printf("printing MONGO_HOST: %v", os.Getenv("MONGO_HOST"))
log.Println("dropping the wizards collection and seeding database")
err = seedData()
if err != nil {
log.Fatalf("failed to seed the DB: %v", err)
}
log.Printf("finished seeding the database")
lis, err := net.Listen("tcp", ":"+os.Getenv("WIZARDS_SERVER_GRPC_PORT"))
if err != nil {
log.Fatalf("could not listen: %v", err)
}
grpcServer := grpc.NewServer()
pb.RegisterWizardServiceServer(grpcServer, &server{})
log.Println("# ----------------------------------- #")
log.Printf("running grpc server on port: %v", os.Getenv("WIZARDS_SERVER_GRPC_PORT"))
log.Println("# ----------------------------------- #")
err = grpcServer.Serve(lis)
if err != nil {
log.Fatalf("failed to start the grpc server: %s", err)
log.Fatalln("trivial")
}
}
//List is the gRPC service method that retrieves a list of wizards from the database and streams back to the client
func (s *server) List(e *pb.EmptyRequest, srv pb.WizardService_ListServer) error {
log.Println("# -------------------------------------- #")
log.Println("sending list of wizards to client")
log.Println("# -------------------------------------- #")
dbConnectionString := "mongodb://" + os.Getenv("MONGO_HOST") + ":" + "27017" + "/" + os.Getenv("MONGO_DATABASE")
client, err := mongo.NewClient(options.Client().ApplyURI(dbConnectionString))
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err = client.Connect(ctx)
defer func() {
err = client.Disconnect(ctx)
if err != nil {
log.Fatalf("failed to disconnect client: %v", err)
}
}()
// test connection
err = client.Ping(ctx, readpref.Primary())
if err != nil {
log.Fatalf("error pinging DB: %v", err)
}
db := client.Database("wizards")
// set find options behavior
findOptions := options.Find()
// findOptions.SetLimit(25)
// filter by company, this is the default behavior
filter := bson.D{{}}
cursor, err := db.Collection("wizards").Find(ctx, filter, findOptions)
if err != nil {
log.Printf("failed to get wizards: %v", err)
}
defer cursor.Close(context.Background())
for cursor.Next(context.Background()) {
var wizard pb.Wizard
err := cursor.Decode(&wizard)
if err != nil {
log.Printf("unable to decode wizard cursor into struct: %v", err)
}
// Commenting out. Uncomment when making the server change in the demo
// switch house := wizard.House; house {
// case "Gryffindor":
// log.Printf("%v - sending wizard to client: %v", emoji.Eagle, wizard.GetName())
// case "Ravenclaw":
// log.Printf("%v - sending wizard to client: %v", emoji.Bird, wizard.GetName())
// case "Hufflepuff":
// log.Printf("%v - sending wizard to client: %v", emoji.Badger, wizard.GetName())
// case "Slytherin":
// log.Printf("%v - sending wizard to client: %v", emoji.Snake, wizard.GetName())
// }
// comment this log statement as part of the server demo
log.Printf("sending wizard to client: %v", wizard.GetName())
err = srv.Send(&wizard)
if err != nil {
log.Printf("send error: %v", err)
}
}
err = cursor.Err()
if err != nil {
log.Printf("error with the client cursor: %v", err)
}
// uncomment before building the docker image with Bazel
// log.Println("")
// log.Println("built with Bazel")
// log.Println("")
log.Println("# -------------------------------------- #")
log.Println("done sending list of wizards to client")
log.Println("# -------------------------------------- #")
return nil
}
// loadConfigs looks for a specific file of key=value pairs and loads them as variables for the runtime instance
func loadConfigs() {
file, err := os.Open(configMapFile)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
// fmt.Println(scanner.Text())
s := strings.Split(scanner.Text(), "=")
os.Setenv(s[0], s[1])
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
log.Println("done setting environment variables")
}
// seedData drops the wizards collection and seeds it with fresh data to the demo
func seedData() error {
dbConnectionString := "mongodb://" + os.Getenv("MONGO_HOST") + ":" + "27017" + "/" + os.Getenv("MONGO_DATABASE")
client, err := mongo.NewClient(options.Client().ApplyURI(dbConnectionString))
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err = client.Connect(ctx)
defer func() {
err = client.Disconnect(ctx)
if err != nil {
log.Fatalf("failed to disconnect client: %v", err)
}
}()
// test connection
err = client.Ping(ctx, readpref.Primary())
if err != nil {
log.Fatalf("error pinging DB: %v", err)
}
db := client.Database("wizards")
// // drop the collection in order to see fresh data for a new run
err = db.Collection("wizards").Drop(context.Background())
if err != nil {
log.Fatal("unable drop the wizard collection")
}
// seed the database
wizards := []pb.Wizard{
{Name: "Harry Potter",
House: "Gryffindor",
DeathEater: false,
},
{Name: "Ron Weasley",
House: "Gryffindor",
DeathEater: false,
},
{Name: "Hermione Granger",
House: "Gryffindor",
DeathEater: false,
},
{Name: "Cho Chang",
House: "Ravenclaw",
DeathEater: false,
},
{Name: "Luna Lovegood",
House: "Ravenclaw",
DeathEater: false,
},
{Name: "Sybill Trelawney",
House: "Ravenclaw",
DeathEater: false,
},
{Name: "Pomona Sprout",
House: "Hufflepuff",
DeathEater: false,
},
{Name: "Cedric Diggory",
House: "Hufflepuff",
DeathEater: false,
},
{Name: "Newton Scamander",
House: "Hufflepuff",
DeathEater: false,
},
{Name: "Draco Malfoy",
House: "Slytherin",
DeathEater: true,
},
{Name: "Bellatrix Lestrange",
House: "Slytherin",
DeathEater: true,
},
{Name: "Severus Snape",
House: "Slytherin",
DeathEater: false,
},
}
log.Printf("connected to the database")
for i := range wizards {
_, err = db.Collection("wizards").InsertOne(ctx, wizards[i])
if err != nil {
log.Fatalf("failed to insert document: %v", err)
}
log.Printf("inserted document for wizard: %s", wizards[i].Name)
i++
}
log.Printf("inserted %v documents", len(wizards))
return err
}