Fix JSON client example and Update documentation. (#67)
* Updated the JSON client to be consistent with the library. The JSON client requires two JSONs, 1. JOB json -- contains job description. 2. Config json -- contains configuration information such as username, password, schedulerUrl, zookeeper cluster configuration etc. * Job json using docker-compose executor. Used https://github.com/paypal/dce-go/blob/develop/examples/client.go#L50 to create a json file for a job that uses the docker-compose executor. The current job json file (examples/job.json) uses an outdated version of docker-compose executor. Once examples/client.go has been modified to use examples/job_dce.json, it should be okay to get rid of examples/job.json. * Run thermos jobs using json client. Added an extra field to JobJson, ExecutorDataFile, that holds the path to the json file representing the executor configuration data. Added a new example job json file (examples/job_thermos.json) that is to be passed to the json client along with the config file to run a thermos job. * Using scheduler URL instead of leader from zk. The endpoints returned by ZKEndpoints(...) is not reachable from outside the vagrant box. Hence, using the scheduler URL directly. * Added docs for using dce-go and json client. * Place json client docs in separate subsection. * Config now embeds realis.Cluster to be backwards compatible with the python client cluster.json file. Changed the type of Transport to string to stay flexible if new transport types come up. JSON is used as the default transport option is not transport is provided with the config.
This commit is contained in:
parent
fe567ee966
commit
0e4a0d726b
5 changed files with 238 additions and 69 deletions
|
@ -94,6 +94,15 @@ client must be used in order to launch tasks using a custom executor. In this ca
|
|||
we will be using [gorealis](https://github.com/paypal/gorealis) to launch a task with
|
||||
the compose executor on Aurora.
|
||||
|
||||
## Using [dce-go](https://github.com/paypal/dce-go)
|
||||
Instead of manually configuring Aurora to run the docker-compose executor, one can follow the instructions provided [here](https://github.com/paypal/dce-go/blob/develop/docs/environment.md) to quickly create a DCE environment that would include mesos, aurora, golang1.7, docker, docker-compose and DCE installed.
|
||||
|
||||
Please note that when using dce-go, the endpoints are going to be as shown below,
|
||||
```
|
||||
Aurora endpoint --> http://192.168.33.8:8081
|
||||
Mesos endpoint --> http://192.168.33.8:5050
|
||||
```
|
||||
|
||||
## Configuring the system to run a custom client and docker-compose executor
|
||||
|
||||
### Installing Go
|
||||
|
@ -162,7 +171,7 @@ $ source $HOME/.profile
|
|||
|
||||
Download and run the msi installer from https://golang.org/dl/
|
||||
|
||||
## Installing Docker Compose
|
||||
## Installing Docker Compose (if manually configured Aurora)
|
||||
To show Aurora's new multi executor feature, we need to use at least one custom executor.
|
||||
In this case we will be using the [docker-compose-executor](https://github.com/mesos/docker-compose-executor).
|
||||
|
||||
|
@ -263,7 +272,7 @@ A message from the executor should greet us.
|
|||
It is also possible to create a thermos job using gorealis. To do this, however,
|
||||
a thermos payload is required. A thermos payload consists of a JSON blob that details
|
||||
the entire task as it exists inside the Aurora Scheduler. *Creating the blob is unfortunately
|
||||
out of the scope of was gorealis does*, so a thermos payload must be generated beforehand or
|
||||
out of the scope of what gorealis does*, so a thermos payload must be generated beforehand or
|
||||
retrieved from the structdump of an existing task for testing purposes.
|
||||
|
||||
A sample thermos JSON payload may be found [here](../examples/thermos_payload.json) in the examples folder.
|
||||
|
@ -292,13 +301,32 @@ $ cd $GOPATH/src/github.com/paypal/gorealis
|
|||
$ go run examples/client.go -executor=thermos -url=http://192.168.33.7:8081 -cmd=create -executor=thermos
|
||||
```
|
||||
|
||||
## Creating jobs using gorealis JSON client
|
||||
We can also use the [JSON client](../examples/jsonClient.go) to create Aurora jobs using gorealis.
|
||||
|
||||
If using _dce-go_, then use `http://192.168.33.8:8081` as the scheduler URL.
|
||||
|
||||
```
|
||||
$ cd $GOPATH/src/github.com/paypal/gorealis/examples
|
||||
```
|
||||
|
||||
To launch a job using the Thermos executor,
|
||||
```
|
||||
$ go run jsonClient.go -job=job_thermos.json -config=config.json
|
||||
```
|
||||
|
||||
To launch a job using docker-compose executor,
|
||||
```
|
||||
$ go run jsonClient.go -job=job_dce.json -config=config.json
|
||||
```
|
||||
|
||||
# Cleaning up
|
||||
|
||||
To stop the jobs we've launched, we need to send a job kill request to Aurora.
|
||||
It should be noted that although we can't create jobs using a custom executor using the default Aurora client,
|
||||
we ~can~ use the default Aurora client to kill them. Additionally, we can use gorealis perform the clean up as well.
|
||||
|
||||
## Using the Default Client
|
||||
## Using the Default Client (if manually configured Aurora)
|
||||
|
||||
```
|
||||
$ aurora job killall devcluster/www-data/prod/hello
|
||||
|
|
13
examples/config.json
Normal file
13
examples/config.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"username": "aurora",
|
||||
"password": "secret",
|
||||
"sched_url": "http://192.168.33.7:8081",
|
||||
"cluster" : {
|
||||
"name": "devcluster",
|
||||
"zk": "192.168.33.7",
|
||||
"scheduler_zk_path": "/aurora/scheduler",
|
||||
"auth_mechanism": "UNAUTHENTICATED",
|
||||
"slave_run_directory": "latest",
|
||||
"slave_root": "/var/lib/mesos"
|
||||
}
|
||||
}
|
21
examples/job_dce.json
Normal file
21
examples/job_dce.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "sampleapp",
|
||||
"cpu": 0.25,
|
||||
"ram_mb": 256,
|
||||
"disk_mb": 100,
|
||||
"executor": "docker-compose-executor",
|
||||
"service": true,
|
||||
"ports": 4,
|
||||
"instances": 1,
|
||||
"uris": [
|
||||
{
|
||||
"uri": "http://192.168.33.8/app.tar.gz",
|
||||
"extract": true,
|
||||
"cache": false
|
||||
}
|
||||
],
|
||||
"labels":{
|
||||
"fileName":"sampleapp/docker-compose.yml,sampleapp/docker-compose-healthcheck.yml"
|
||||
}
|
||||
|
||||
}
|
11
examples/job_thermos.json
Normal file
11
examples/job_thermos.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "hello_world_from_gorealis",
|
||||
"cpu": 1.0,
|
||||
"ram_mb": 64,
|
||||
"disk_mb": 100,
|
||||
"executor": "thermos",
|
||||
"exec_data_file": "examples/thermos_payload.json",
|
||||
"service": true,
|
||||
"ports": 1,
|
||||
"instances": 1
|
||||
}
|
|
@ -18,9 +18,13 @@ import (
|
|||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/paypal/gorealis"
|
||||
"github.com/paypal/gorealis/gen-go/apache/aurora"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type URIJson struct {
|
||||
|
@ -30,16 +34,17 @@ type URIJson struct {
|
|||
}
|
||||
|
||||
type JobJson struct {
|
||||
Name string `json:"name"`
|
||||
CPU float64 `json:"cpu"`
|
||||
RAM int64 `json:"ram_mb"`
|
||||
Disk int64 `json:"disk_mb"`
|
||||
Executor string `json:"executor"`
|
||||
Instances int32 `json:"instances"`
|
||||
URIs []URIJson `json:"uris"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Service bool `json:"service"`
|
||||
Ports int `json:"ports"`
|
||||
Name string `json:"name"`
|
||||
CPU float64 `json:"cpu"`
|
||||
RAM int64 `json:"ram_mb"`
|
||||
Disk int64 `json:"disk_mb"`
|
||||
Executor string `json:"executor"`
|
||||
ExecutorDataFile string `json:"exec_data_file,omitempty"`
|
||||
Instances int32 `json:"instances"`
|
||||
URIs []URIJson `json:"uris"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Service bool `json:"service"`
|
||||
Ports int `json:"ports"`
|
||||
}
|
||||
|
||||
func (j *JobJson) Validate() bool {
|
||||
|
@ -63,67 +68,158 @@ func (j *JobJson) Validate() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func main() {
|
||||
type Config struct {
|
||||
realis.Cluster `json:"cluster"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
SchedUrl string `json:"sched_url"`
|
||||
Transport string `json:"transport,omitempty"`
|
||||
Debug bool `json:"debug,omitempty"`
|
||||
}
|
||||
|
||||
// Command-line arguments for config and job JSON files.
|
||||
var configJSONFile, jobJSONFile string
|
||||
|
||||
var job *JobJson
|
||||
var config *Config
|
||||
|
||||
// Reading command line arguments and validating.
|
||||
// If Aurora scheduler URL not provided, then using zookeeper to locate the leader.
|
||||
func init() {
|
||||
flag.StringVar(&configJSONFile, "config", "./config.json", "The config file that contains username, password, and the cluster configuration information.")
|
||||
flag.StringVar(&jobJSONFile, "job", "./job.json", "JSON file containing job definitions.")
|
||||
|
||||
jsonFile := flag.String("file", "", "JSON file containing job definition")
|
||||
flag.Parse()
|
||||
|
||||
if *jsonFile == "" {
|
||||
job = new(JobJson)
|
||||
config = new(Config)
|
||||
|
||||
if jobsFile, jobJSONReadErr := os.Open(jobJSONFile); jobJSONReadErr != nil {
|
||||
flag.Usage()
|
||||
fmt.Println("Error reading the job JSON file: ", jobJSONReadErr)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
if unmarshallErr := json.NewDecoder(jobsFile).Decode(job); unmarshallErr != nil {
|
||||
flag.Usage()
|
||||
fmt.Println("Error parsing job json file: ", unmarshallErr)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Need to validate the job JSON file.
|
||||
if !job.Validate() {
|
||||
fmt.Println("Invalid Job.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Open(*jsonFile)
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file ", err)
|
||||
if configFile, configJSONErr := os.Open(configJSONFile); configJSONErr != nil {
|
||||
flag.Usage()
|
||||
fmt.Println("Error reading the config JSON file: ", configJSONErr)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
if unmarshallErr := json.NewDecoder(configFile).Decode(config); unmarshallErr != nil {
|
||||
fmt.Println("Error parsing config JSON file: ", unmarshallErr)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CreateRealisClient(config *Config) (realis.Realis, error) {
|
||||
var transportOption realis.ClientOption
|
||||
// Configuring transport protocol. If not transport is provided, then using JSON as the
|
||||
// default transport protocol.
|
||||
switch config.Transport {
|
||||
case "binary":
|
||||
transportOption = realis.ThriftBinary()
|
||||
case "json", "":
|
||||
transportOption = realis.ThriftJSON()
|
||||
default:
|
||||
fmt.Println("Invalid transport option provided!")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
clientOptions := []realis.ClientOption{
|
||||
realis.BasicAuth(config.Username, config.Password),
|
||||
transportOption,
|
||||
realis.ZKCluster(&config.Cluster),
|
||||
// realis.SchedulerUrl(config.SchedUrl),
|
||||
realis.SetLogger(log.New(os.Stdout, "realis-debug: ", log.Ldate)),
|
||||
realis.BackOff(realis.Backoff{
|
||||
Steps: 2,
|
||||
Duration: 10 * time.Second,
|
||||
Factor: 2.0,
|
||||
Jitter: 0.1,
|
||||
}),
|
||||
}
|
||||
|
||||
if config.Debug {
|
||||
clientOptions = append(clientOptions, realis.Debug())
|
||||
}
|
||||
|
||||
return realis.NewRealisClient(clientOptions...)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if r, clientCreationErr := CreateRealisClient(config); clientCreationErr != nil {
|
||||
fmt.Println(clientCreationErr)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
monitor := &realis.Monitor{Client: r}
|
||||
defer r.Close()
|
||||
uris := job.URIs
|
||||
labels := job.Labels
|
||||
|
||||
auroraJob := realis.NewJob().
|
||||
Environment("prod").
|
||||
Role("vagrant").
|
||||
Name(job.Name).
|
||||
CPU(job.CPU).
|
||||
RAM(job.RAM).
|
||||
Disk(job.Disk).
|
||||
IsService(job.Service).
|
||||
InstanceCount(job.Instances).
|
||||
AddPorts(job.Ports)
|
||||
|
||||
// If thermos executor, then reading in the thermos payload.
|
||||
if (job.Executor == aurora.AURORA_EXECUTOR_NAME) || (job.Executor == "thermos") {
|
||||
payload, err := ioutil.ReadFile(job.ExecutorDataFile)
|
||||
if err != nil {
|
||||
fmt.Println(errors.Wrap(err, "Invalid thermos payload file!"))
|
||||
os.Exit(1)
|
||||
}
|
||||
auroraJob.ExecutorName(aurora.AURORA_EXECUTOR_NAME).
|
||||
ExecutorData(string(payload))
|
||||
} else {
|
||||
auroraJob.ExecutorName(job.Executor)
|
||||
}
|
||||
|
||||
// Adding URIs.
|
||||
for _, uri := range uris {
|
||||
auroraJob.AddURIs(uri.Extract, uri.Cache, uri.URI)
|
||||
}
|
||||
|
||||
// Adding Labels.
|
||||
for key, value := range labels {
|
||||
auroraJob.AddLabel(key, value)
|
||||
}
|
||||
|
||||
fmt.Println("Creating Job...")
|
||||
if resp, jobCreationErr := r.CreateJob(auroraJob); jobCreationErr != nil {
|
||||
fmt.Println("Error creating Aurora job: ", jobCreationErr)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
if resp.ResponseCode == aurora.ResponseCode_OK {
|
||||
if ok, monitorErr := monitor.Instances(auroraJob.JobKey(), auroraJob.GetInstanceCount(), 5, 50); !ok || monitorErr != nil {
|
||||
if _, jobErr := r.KillJob(auroraJob.JobKey()); jobErr !=
|
||||
nil {
|
||||
fmt.Println(jobErr)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
fmt.Println("ok: ", ok)
|
||||
fmt.Println("jobErr: ", jobErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsonJob := new(JobJson)
|
||||
|
||||
err = json.NewDecoder(file).Decode(jsonJob)
|
||||
if err != nil {
|
||||
fmt.Println("Error parsing file ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
jsonJob.Validate()
|
||||
|
||||
//Create new configuration with default transport layer
|
||||
config, err := realis.NewDefaultConfig("http://192.168.33.7:8081")
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
realis.AddBasicAuth(&config, "aurora", "secret")
|
||||
r := realis.NewClient(config)
|
||||
|
||||
auroraJob := realis.NewJob().
|
||||
Environment("prod").
|
||||
Role("vagrant").
|
||||
Name(jsonJob.Name).
|
||||
CPU(jsonJob.CPU).
|
||||
RAM(jsonJob.RAM).
|
||||
Disk(jsonJob.Disk).
|
||||
ExecutorName(jsonJob.Executor).
|
||||
InstanceCount(jsonJob.Instances).
|
||||
IsService(jsonJob.Service).
|
||||
AddPorts(jsonJob.Ports)
|
||||
|
||||
for _, uri := range jsonJob.URIs {
|
||||
auroraJob.AddURIs(uri.Extract, uri.Cache, uri.URI)
|
||||
}
|
||||
|
||||
for k, v := range jsonJob.Labels {
|
||||
auroraJob.AddLabel(k, v)
|
||||
}
|
||||
|
||||
resp, err := r.CreateJob(auroraJob)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println(resp)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue