Skip to content

Commit 714ffb9

Browse files
authored
Merge pull request #1529 from spaceuptech/v0.21.0
v0.21.0
2 parents 1f49871 + ed37cda commit 714ffb9

File tree

182 files changed

+15644
-7626
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+15644
-7626
lines changed

dbevents/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ COPY --from=stage0 --chown=demiourgos728:root /1/opt/docker /opt/docker
2323
COPY --from=stage0 --chown=demiourgos728:root /2/opt/docker /opt/docker
2424
COPY --from=stage1 --chown=demiourgos728:root /build/app /usr/local/bin/conn-string-parser
2525
COPY --chown=demiourgos728:root src/main/resources/application.conf /config/application.conf
26+
RUN chmod -R 0777 /opt/docker
2627
USER 1001:0
2728
ENTRYPOINT ["/opt/docker/bin/db-events-soruce"]
2829
CMD []

dbevents/build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name := "db-events-soruce"
22

3-
version := "0.1.0"
3+
version := "0.2.0"
44

55
scalaVersion := "2.13.1"
66

dbevents/src/main/scala/com/spaceuptech/dbevents/database/Utils.scala

+72-44
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
package com.spaceuptech.dbevents.database
22

3-
import java.nio.ByteBuffer
4-
import java.util.{Calendar, Properties}
5-
import java.util.concurrent.{Callable, ExecutorService}
6-
import java.util.function.Consumer
7-
83
import akka.actor.typed.ActorRef
94
import com.mongodb.client.model.changestream.{ChangeStreamDocument, FullDocument, OperationType}
105
import com.mongodb.{MongoClient, MongoClientURI}
116
import com.spaceuptech.dbevents.database.Database.ChangeRecord
127
import com.spaceuptech.dbevents.{DatabaseSource, Global}
138
import io.debezium.engine.format.Json
149
import io.debezium.engine.{ChangeEvent, DebeziumEngine}
15-
import org.bson.{BsonDocument, Document}
10+
import org.bson.{BsonDocument, BsonType, BsonValue, Document}
1611
import org.json4s._
1712
import org.json4s.jackson.JsonMethods._
1813

14+
import java.nio.ByteBuffer
15+
import java.time.{Instant, OffsetDateTime, ZoneId}
16+
import java.util.concurrent.{Callable, ExecutorService}
17+
import java.util.function.Consumer
18+
import java.util.{Calendar, Properties}
19+
1920
object Utils {
2021
def startMongoWatcher(projectId: String, dbAlias: String, conn: String, dbName: String, executorService: ExecutorService, actor: ActorRef[Database.Command]): MongoStatus = {
2122
// Make a mongo client
@@ -58,7 +59,7 @@ object Utils {
5859
payload = ChangeRecordPayload(
5960
op = "c",
6061
before = None,
61-
after = Some(mongoDocumentToMap(doc.getFullDocument)),
62+
after = Some(mongoBsonValueToValue(doc.getFullDocument.toBsonDocument(classOf[BsonValue], MongoClient.getDefaultCodecRegistry)).asInstanceOf[Map[String, Any]]),
6263
source = getMongoSource(projectId, dbAlias, doc)
6364
),
6465
project = projectId,
@@ -72,7 +73,7 @@ object Utils {
7273
payload = ChangeRecordPayload(
7374
op = "u",
7475
before = Option(mongoDocumentKeyToMap(doc.getDocumentKey)),
75-
after = Some(mongoDocumentToMap(doc.getFullDocument)),
76+
after = Some(mongoBsonValueToValue(doc.getFullDocument.toBsonDocument(classOf[BsonValue], MongoClient.getDefaultCodecRegistry)).asInstanceOf[Map[String, Any]]),
7677
source = getMongoSource(projectId, dbAlias, doc)
7778
),
7879
project = projectId,
@@ -130,7 +131,7 @@ object Utils {
130131
BsonDocument.parse(new String(data.array(), "UTF-8"))
131132
}
132133

133-
def mongoDocumentKeyToMap(find: BsonDocument): Map[String, Any] = {
134+
def mongoDocumentKeyToMap(find: BsonDocument): Map[String, Any] = {
134135
var id: String = ""
135136
val field = find.get("_id")
136137

@@ -145,21 +146,50 @@ object Utils {
145146
Map("_id" -> id)
146147
}
147148

148-
def mongoDocumentToMap(doc: Document): Map[String, Any] = {
149-
implicit val formats: DefaultFormats.type = org.json4s.DefaultFormats
150-
151-
// Convert to json object
152-
val jsonString = doc.toJson
153-
var m = parse(jsonString).extract[Map[String, Any]]
154-
155-
// See _id is an object id
156-
try {
157-
m += "_id" -> doc.getObjectId("_id").toHexString
158-
} catch {
159-
case _: Throwable =>
149+
def mongoBsonValueToValue(value: BsonValue): Any = {
150+
// Skip if value is null
151+
if (value == null) return null
152+
153+
value.getBsonType match {
154+
case BsonType.INT32 =>
155+
value.asInt32().getValue
156+
case BsonType.INT64 =>
157+
value.asInt64().getValue
158+
case BsonType.OBJECT_ID =>
159+
value.asObjectId().getValue.toHexString
160+
case BsonType.DATE_TIME =>
161+
OffsetDateTime.ofInstant(Instant.ofEpochMilli(value.asDateTime().getValue), ZoneId.systemDefault()).toString
162+
case BsonType.TIMESTAMP =>
163+
OffsetDateTime.ofInstant(Instant.ofEpochMilli(value.asTimestamp().getValue), ZoneId.systemDefault()).toString
164+
case BsonType.DOCUMENT =>
165+
val doc = value.asDocument().toBsonDocument(classOf[BsonDocument], MongoClient.getDefaultCodecRegistry)
166+
var obj: Map[String, Any] = Map.empty
167+
doc.keySet().forEach(key => {
168+
obj += (key -> mongoBsonValueToValue(doc.get(key)))
169+
})
170+
obj
171+
case BsonType.ARRAY =>
172+
val arr = value.asArray().getValues
173+
var op: Array[Any] = Array.empty
174+
175+
arr.forEach(value => {
176+
op = op :+ mongoBsonValueToValue(value)
177+
})
178+
179+
op
180+
case BsonType.BOOLEAN =>
181+
value.asBoolean().getValue
182+
case BsonType.STRING =>
183+
value.asString().getValue
184+
case BsonType.DOUBLE =>
185+
value.asDouble().getValue
186+
case BsonType.DECIMAL128 =>
187+
value.asDecimal128().doubleValue()
188+
case BsonType.BINARY =>
189+
value.asBinary().getData
190+
case _ =>
191+
value.toString
160192
}
161-
162-
m
163193
}
164194

165195
def getMongoSource(projectId: String, dbAlias: String, doc: ChangeStreamDocument[Document]): ChangeRecordPayloadSource = {
@@ -232,6 +262,24 @@ object Utils {
232262
props
233263
}
234264

265+
def getOffsetStorageClass: String = {
266+
Global.storageType match {
267+
case "k8s" => "com.spaceuptech.dbevents.database.KubeOffsetBackingStore"
268+
case _ => "org.apache.kafka.connect.storage.FileOffsetBackingStore"
269+
}
270+
}
271+
272+
def getDatabaseHistoryStorageClass: String = {
273+
Global.storageType match {
274+
case "k8s" => "com.spaceuptech.dbevents.database.KubeDatabaseHistory"
275+
case _ => "io.debezium.relational.history.FileDatabaseHistory"
276+
}
277+
}
278+
279+
def generateConnectorName(source: DatabaseSource): String = {
280+
s"${source.project}_${source.dbAlias}"
281+
}
282+
235283
def prepareSQLServerConfig(source: DatabaseSource): Properties = {
236284
val name = generateConnectorName(source)
237285

@@ -247,16 +295,14 @@ object Utils {
247295
props.setProperty("database.hostname", source.config.getOrElse("host", "localhost"))
248296
props.setProperty("database.port", source.config.getOrElse("port", "1433"))
249297
props.setProperty("database.user", source.config.getOrElse("user", "sa"))
250-
props.setProperty("database.password", source.config.getOrElse("password", "mypassword"))
298+
props.setProperty("database.password", source.config.getOrElse("password", "password"))
251299
props.setProperty("database.dbname", source.config.getOrElse("db", "test"))
252300
props.setProperty("database.server.name", s"${generateConnectorName(source)}_connector")
253301
props.setProperty("database.history", getDatabaseHistoryStorageClass)
254302
props.setProperty("database.history.file.filename", s"./dbevents-dbhistory-$name.dat")
255303
props
256304
}
257305

258-
259-
260306
def preparePostgresConfig(source: DatabaseSource): Properties = {
261307
val name = generateConnectorName(source)
262308

@@ -284,22 +330,4 @@ object Utils {
284330

285331
props
286332
}
287-
288-
def getOffsetStorageClass: String = {
289-
Global.storageType match {
290-
case "k8s" => "com.spaceuptech.dbevents.database.KubeOffsetBackingStore"
291-
case _ => "org.apache.kafka.connect.storage.FileOffsetBackingStore"
292-
}
293-
}
294-
295-
def getDatabaseHistoryStorageClass: String = {
296-
Global.storageType match {
297-
case "k8s" => "com.spaceuptech.dbevents.database.KubeDatabaseHistory"
298-
case _ => "io.debezium.relational.history.FileDatabaseHistory"
299-
}
300-
}
301-
302-
def generateConnectorName(source: DatabaseSource): String = {
303-
s"${source.project}_${source.dbAlias}"
304-
}
305333
}

gateway/Dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM golang:1.15.3-alpine3.12
22
WORKDIR /build
33

44
# Take the current space cloud version as a argument
5-
ARG SC_VERSION=0.20.1
5+
ARG SC_VERSION=0.21.0
66

77
# Copy all the source files
88
COPY . .
@@ -16,7 +16,7 @@ RUN GOOS=linux CGO_ENABLED=0 go build -a -ldflags '-s -w -extldflags "-static"'
1616
RUN echo $SC_VERSION && wget https://storage.googleapis.com/space-cloud/mission-control/mission-control-v$SC_VERSION.zip && unzip mission-control-v$SC_VERSION.zip
1717

1818
FROM alpine:3.12
19-
ARG SC_VERSION=0.20.1
19+
ARG SC_VERSION=0.21.0
2020

2121
RUN apk --no-cache add ca-certificates
2222

gateway/config/config.go

+24-13
Original file line numberDiff line numberDiff line change
@@ -303,19 +303,24 @@ type Service struct {
303303

304304
// Endpoint holds the config of a endpoint
305305
type Endpoint struct {
306-
Kind EndpointKind `json:"kind" yaml:"kind" mapstructure:"kind"`
307-
Tmpl TemplatingEngine `json:"template,omitempty" yaml:"template,omitempty" mapstructure:"template"`
308-
ReqTmpl string `json:"requestTemplate" yaml:"requestTemplate" mapstructure:"requestTemplate"`
309-
GraphTmpl string `json:"graphTemplate" yaml:"graphTemplate" mapstructure:"graphTemplate"`
310-
ResTmpl string `json:"responseTemplate" yaml:"responseTemplate" mapstructure:"responseTemplate"`
311-
OpFormat string `json:"outputFormat,omitempty" yaml:"outputFormat,omitempty" mapstructure:"outputFormat"`
312-
Token string `json:"token,omitempty" yaml:"token,omitempty" mapstructure:"token"`
313-
Claims string `json:"claims,omitempty" yaml:"claims,omitempty" mapstructure:"claims"`
314-
Method string `json:"method" yaml:"method" mapstructure:"method"`
315-
Path string `json:"path" yaml:"path" mapstructure:"path"`
316-
Rule *Rule `json:"rule,omitempty" yaml:"rule,omitempty" mapstructure:"rule"`
317-
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers"`
318-
Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout"` // Timeout is in seconds
306+
Kind EndpointKind `json:"kind" yaml:"kind" mapstructure:"kind"`
307+
Tmpl TemplatingEngine `json:"template,omitempty" yaml:"template,omitempty" mapstructure:"template"`
308+
// ReqPayloadFormat specifies the payload format
309+
// depending upon the payload format, the graphQL request that
310+
// gets converted to http request will use that format as it's payload
311+
// currently supported formats are application/json,multipart/form-data
312+
ReqPayloadFormat string `json:"requestPayloadFormat" yaml:"requestPayloadFormat" mapstructure:"requestPayloadFormat"`
313+
ReqTmpl string `json:"requestTemplate" yaml:"requestTemplate" mapstructure:"requestTemplate"`
314+
GraphTmpl string `json:"graphTemplate" yaml:"graphTemplate" mapstructure:"graphTemplate"`
315+
ResTmpl string `json:"responseTemplate" yaml:"responseTemplate" mapstructure:"responseTemplate"`
316+
OpFormat string `json:"outputFormat,omitempty" yaml:"outputFormat,omitempty" mapstructure:"outputFormat"`
317+
Token string `json:"token,omitempty" yaml:"token,omitempty" mapstructure:"token"`
318+
Claims string `json:"claims,omitempty" yaml:"claims,omitempty" mapstructure:"claims"`
319+
Method string `json:"method" yaml:"method" mapstructure:"method"`
320+
Path string `json:"path" yaml:"path" mapstructure:"path"`
321+
Rule *Rule `json:"rule,omitempty" yaml:"rule,omitempty" mapstructure:"rule"`
322+
Headers Headers `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers"`
323+
Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty" mapstructure:"timeout"` // Timeout is in seconds
319324
}
320325

321326
// EndpointKind describes the type of endpoint. Default value - internal
@@ -330,6 +335,12 @@ const (
330335

331336
// EndpointKindPrepared describes an endpoint on on Space Cloud GraphQL layer
332337
EndpointKindPrepared EndpointKind = "prepared"
338+
339+
// EndpointRequestPayloadFormatJSON specifies json payload format for the request
340+
EndpointRequestPayloadFormatJSON string = "json"
341+
342+
// EndpointRequestPayloadFormatFormData specifies multipart/form-data payload format for the request
343+
EndpointRequestPayloadFormatFormData string = "form-data"
333344
)
334345

335346
// TemplatingEngine describes the type of endpoint. Default value - go

gateway/go.mod

+4-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ require (
55
github.com/Masterminds/goutils v1.1.0 // indirect
66
github.com/Masterminds/semver v1.5.0 // indirect
77
github.com/Masterminds/sprig v2.22.0+incompatible
8-
github.com/aws/aws-sdk-go v1.33.14
8+
github.com/aws/aws-sdk-go v1.34.28
99
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
1010
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
1111
github.com/dgrijalva/jwt-go v3.2.0+incompatible
@@ -37,16 +37,14 @@ require (
3737
github.com/rs/cors v1.7.0
3838
github.com/satori/go.uuid v1.2.0
3939
github.com/segmentio/ksuid v1.0.3
40-
github.com/spaceuptech/helpers v0.1.2
40+
github.com/spaceuptech/helpers v0.2.1
4141
github.com/spaceuptech/space-api-go v0.18.1
4242
github.com/stretchr/objx v0.2.0 // indirect
43-
github.com/stretchr/testify v1.6.1
44-
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51 // indirect
43+
github.com/stretchr/testify v1.7.0
4544
github.com/urfave/cli v1.22.2
46-
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
4745
github.com/xdg/stringprep v1.0.0 // indirect
4846
go.etcd.io/bbolt v1.3.3
49-
go.mongodb.org/mongo-driver v1.1.1
47+
go.mongodb.org/mongo-driver v1.4.4
5048
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
5149
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0
5250
google.golang.org/api v0.18.0

0 commit comments

Comments
 (0)