Before I can start writing about the s3 storage provider implementation, I should probably document how to run and configure reva, so that you can better understand how it works. Let’s dive right into it:
$ git clone git@github.com:cernbox/reva && cd reva
$ make
$ ./cmd/revad/revad -c cmd/revad/basic-revad.toml -p revad.pid &> revad.log &
[1] 4003
$ curl localhost:9998
Hello World!%
$ kill %1
[1] + 4003 terminated ./cmd/revad/revad -c cmd/revad/basic-revad.toml -p revad.pid &> revad.log
Ok, so let me unpack the above:
-
cernbox/reva
is the upstream project. Our changes live inowncloud/reva
so we can keep track of our builds and PRs independently. How we collaborate exactly is probably worth another post. For this example I am going to use upstream directly. - Why
make
? It will fill some environment variables and bake the version and git commit into the binary that can later be used to properly identify which code was running. You can of course just rungo build ./cmd/revad
to produce a binary without that magic. - Reva ships with a minimal configuration that we use to get a service up and running:
I also redirected all output to a logfile and gave revad the path to a pidfile. Let’s ignore those for now and focus on the HTTP service.$ cat cmd/revad/basic-revad.toml [http] enabled_services = ["helloworldsvc"]
- As you probably guessed, the
helloworldsvc
does nothing else but renderHello World!
. -
kill %1
, if you are unfamiliar with job control, kills the job number 1, whereaskill 1
kills the process with the pid 1. Two very different things.
Grepping the code
So, where does the service live in the codebase?
$ grep -r -A1 -B1 Hello cmd/revad
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go- }
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go: if conf.HelloMessage == "" {
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go: conf.HelloMessage = "Hello World!"
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go- }
--
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go- Prefix string `mapstructure:"prefix"`
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go: HelloMessage string `mapstructure:"hello_message"`
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go-}
--
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go: w.Write([]byte(s.conf.HelloMessage))
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go- })
Übereinstimmungen in Binärdatei cmd/revad/revad
Interesting, there seems to be a config option for the s.conf.HelloMessage
.
Configuring services
How do we configure that helloworldsvc
?
$ cp cmd/revad/basic-revad.toml myrevad.toml
$ echo "\n[http.services.helloworldsvc]\nhello_message='Hi reva!'" >> myrevad.toml
$ ./cmd/revad/revad -c myrevad.toml -p revad.pid &> revad.log &
[1] 14395
$ curl localhost:9998
Hi reva!%
$ kill %1
The TOML file contains ini like sections. Every service that is registered can be configured in a dedicated section that contains his name.
Registering a service
How is reva made aware of the service? If you look at the codebase you will find several loader.go
files. They all contain a list of packages to make reva aware of them. Finally, a service needs to register itself with either the httpserver
or grpcserver
. For the helloworldsvc
this looks like this:
$ grep -rn helloworldsvc cmd/revad/svcs
cmd/revad/svcs/httpsvcs/loader/loader.go:24: _ "github.com/cernbox/reva/cmd/revad/svcs/httpsvcs/helloworldsvc"
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go:19:package helloworldsvc
cmd/revad/svcs/httpsvcs/helloworldsvc/helloworldsvc.go:31: httpserver.Register("helloworldsvc", New)
httpserver.Register("helloworldsvc", New)
is what makes reva aware of the helloworldsvc
.
Reva is an opinionated framework
The above should give you pointers to the different pieces of a reva service. Putting it all together, you can think of reva as a framework to implement, configure and execute HTTP and GRPC services. It comes with zerolog for logging, a TOML based configuration, prometheus metrics, and provides several go packages that make implementing CS3 services easier. Adding opentracing is planned as well.
Putting config changes into effect
One last thing: do we really have to kill revad to change the config? In theory not:
$ ./cmd/revad/revad -p revad.pid -s reload
signaling master process
That should spawn a new process, test the new config and switch over to the new instance without dropping a request. However that did not work for me … might be a bug.
¯\_(ツ)_/¯
PR welcome!
Cheers!
Next up: how to implement a storage provider for reva.