diff --git a/.goxc.json b/.goxc.json index cf8b194b1..054c62898 100644 --- a/.goxc.json +++ b/.goxc.json @@ -19,7 +19,7 @@ "outputFormat": "by-file-extension", "owner": "victorcoder", "prerelease": true, - "repository": "dcron" + "repository": "dkron" } }, "ConfigVersion": "0.9", diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index f827285be..95c0b70ed 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,5 +1,5 @@ { - "ImportPath": "github.com/victorcoder/dcron", + "ImportPath": "github.com/victorcoder/dkron", "GoVersion": "go1.4", "Deps": [ { diff --git a/LICENSE b/LICENSE index 6e205942d..a19a9f8ac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ Copyright (c) Victor Castell -Dcron is an Open Source project licensed under the terms of +Dkron is an Open Source project licensed under the terms of the LGPLv3 license. Please see for license text. diff --git a/Procfile b/Procfile index c5c093fd5..def925bbe 100644 --- a/Procfile +++ b/Procfile @@ -1,3 +1,3 @@ etc: bin/etcd -name dcron1 -dcron2: godep go run *.go agent -server -node=dcron2 -join=127.0.0.1:5002 -bind=127.0.0.1:5001 -http-addr=:8081 -dcron3: godep go run *.go agent -server -node=dcron3 -join=127.0.0.1:5001 -bind=127.0.0.1:5002 -http-addr=:8082 +dkron2: godep go run *.go agent -server -node=dkron2 -join=127.0.0.1:5002 -bind=127.0.0.1:5001 -http-addr=:8081 +dkron3: godep go run *.go agent -server -node=dkron3 -join=127.0.0.1:5001 -bind=127.0.0.1:5002 -http-addr=:8082 diff --git a/README.md b/README.md index 1dc87a5a8..78a5fabe7 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,26 @@ -# Dcron - Distributed, fault tolerant job scheduling system +# Dkron - Distributed, fault tolerant job scheduling system -Website: http://dcron.io/ +Website: http://dkron.io/ -Dcron is a distributed cron service, easy to setup and fault tolerant with focus in: +Dkron is a distributed cron service, easy to setup and fault tolerant with focus in: - Easy: Easy to use with a great UI - Reliable: Completly fault tolerant - High scalable: Able to handle high volumes of scheduled jobs and thousands of nodes -Dcron is written in Go and leverage the power of etcd and serf for providing fault tolerance and, reliability and scalability while keeping simple and easily instalable. +Dkron is written in Go and leverage the power of etcd and serf for providing fault tolerance and, reliability and scalability while keeping simple and easily instalable. -Dcron is inspired by the google whitepaper [Reliable Cron across the Planet](https://queue.acm.org/detail.cfm?id=2745840) +Dkron is inspired by the google whitepaper [Reliable Cron across the Planet](https://queue.acm.org/detail.cfm?id=2745840) -Dcron runs on Linux, OSX and Windows. It can be used to run scheduled commands on a server cluster using any combination of servers for each job. It has no single points of failure due to the use of the Gossip protocol and the fault tolerant distributed database etcd. +Dkron runs on Linux, OSX and Windows. It can be used to run scheduled commands on a server cluster using any combination of servers for each job. It has no single points of failure due to the use of the Gossip protocol and the fault tolerant distributed database etcd. -You can use Dcron to run the most important part of your company, scheduled jobs. +You can use Dkron to run the most important part of your company, scheduled jobs. ## Status -Currently Dcron is under heavy development and should be considered alpha stage. +Currently Dkron is under heavy development and should be considered alpha stage. -Said that, I encourage you to try it, it's very easy to use, see how it works for you and report any bugs [creating an issue](https://github.com/victorcoder/dcron/issues) in the github project. +Said that, I encourage you to try it, it's very easy to use, see how it works for you and report any bugs [creating an issue](https://github.com/victorcoder/dkron/issues) in the github project. ## Quick start @@ -36,7 +36,7 @@ Next, run the included Procfile `goreman start` -This will start etcd and some Dcron instances that will form a cluster. +This will start etcd and some Dkron instances that will form a cluster. Now you can view the web panel at: http://localhost:8081 @@ -44,4 +44,4 @@ To add jobs to the system read the API docs or take a look to the `job.json` fil ## Documentation -Full, comprehensive documentation is viewable on the Dcron website: http://dcron.io +Full, comprehensive documentation is viewable on the Dkron website: http://dkron.io diff --git a/bower.json b/bower.json index e30235139..ee7e0159c 100644 --- a/bower.json +++ b/bower.json @@ -1,8 +1,8 @@ { - "name": "dcron-dashboard", - "description": "Dcron dashboard", + "name": "dkron-dashboard", + "description": "Dkron dashboard", "version": "0.0.0", - "homepage": "https://dcron.io", + "homepage": "https://dkron.io", "license": "LGPL3", "private": true, "directory": "static/components", diff --git a/config/dcron.json b/config/dkron.json similarity index 68% rename from config/dcron.json rename to config/dkron.json index caa1a6230..683b96552 100644 --- a/config/dcron.json +++ b/config/dkron.json @@ -2,5 +2,6 @@ "tags": { "role": "web", "datacenter": "east" - } + }, + "keyspace": "dcron" } diff --git a/dcron/agent.go b/dkron/agent.go similarity index 95% rename from dcron/agent.go rename to dkron/agent.go index 6951127a5..f63ae47be 100644 --- a/dcron/agent.go +++ b/dkron/agent.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "crypto/sha1" @@ -32,7 +32,7 @@ const ( gracefulTimeout = 3 * time.Second ) -// AgentCommand run dcron server +// AgentCommand run server type AgentCommand struct { Ui cli.Ui Version string @@ -46,8 +46,8 @@ type AgentCommand struct { func (a *AgentCommand) Help() string { helpText := ` -Usage: dcron agent [options] - Run dcron (option -server to run as server) +Usage: dkron agent [options] + Run dkron (option -server to run as server) Options: ` return strings.TrimSpace(helpText) @@ -69,17 +69,19 @@ func (a *AgentCommand) readConfig(args []string) *Config { viper.SetDefault("bind_addr", cmdFlags.Lookup("bind").Value) cmdFlags.String("http-addr", ":8080", "HTTP address") viper.SetDefault("http_addr", cmdFlags.Lookup("http-addr").Value) - cmdFlags.String("discover", "dcron", "mDNS discovery name") + cmdFlags.String("discover", "dkron", "mDNS discovery name") viper.SetDefault("discover", cmdFlags.Lookup("discover").Value) cmdFlags.String("etcd-machines", "http://127.0.0.1:2379", "etcd machines addresses") viper.SetDefault("etcd_machines", cmdFlags.Lookup("etcd-machines").Value) cmdFlags.String("profile", "lan", "timing profile to use (lan, wan, local)") viper.SetDefault("profile", cmdFlags.Lookup("profile").Value) - viper.SetDefault("server", cmdFlags.Bool("server", false, "start dcron server")) + viper.SetDefault("server", cmdFlags.Bool("server", false, "start dkron server")) startJoin := &AppendSliceValue{} cmdFlags.Var(startJoin, "join", "address of agent to join on startup") var tag []string cmdFlags.Var((*AppendSliceValue)(&tag), "tag", "tag pair, specified as key=value") + cmdFlags.String("keyspace", "dkron", "etcd key namespace to use") + viper.SetDefault("keyspace", cmdFlags.Lookup("keyspace").Value) if err := cmdFlags.Parse(args); err != nil { log.Fatal(err) @@ -112,6 +114,7 @@ func (a *AgentCommand) readConfig(args []string) *Config { Profile: viper.GetString("profile"), StartJoin: *startJoin, Tags: tags, + Keyspace: viper.GetString("keyspace"), } // log.Fatal(config.EtcdMachines) @@ -303,7 +306,7 @@ func (a *AgentCommand) Run(args []string) int { a.join(a.config.StartJoin, true) if a.config.Server { - a.etcd = NewEtcdClient(a.config.EtcdMachines, a) + a.etcd = NewEtcdClient(a.config.EtcdMachines, a, a.config.Keyspace) a.sched = NewScheduler() go func() { @@ -369,17 +372,17 @@ func (a *AgentCommand) handleSignals() int { } func (a *AgentCommand) Synopsis() string { - return "Run dcron" + return "Run dkron" } -// Dcron leader election routine +// Leader election routine func (a *AgentCommand) ElectLeader() bool { leaderKey := a.etcd.GetLeader() if leaderKey != "" { if !a.serverAlive(leaderKey) { log.Debug("Trying to set itself as leader") - res, err := a.etcd.Client.CompareAndSwap(keyspace+"/leader", a.config.Tags["key"], 0, leaderKey, 0) + res, err := a.etcd.Client.CompareAndSwap(a.config.Keyspace+"/leader", a.config.Tags["key"], 0, leaderKey, 0) if err != nil { log.Errorln("Error trying to set itself as leader", err) return false @@ -395,18 +398,18 @@ func (a *AgentCommand) ElectLeader() bool { } } else { log.Debug("Trying to set itself as leader") - res, err := a.etcd.Client.Create(keyspace+"/leader", a.config.NodeName, 0) + res, err := a.etcd.Client.Create(a.config.Keyspace+"/leader", a.config.NodeName, 0) if err != nil { log.Error(res, err) } - log.Printf("Successfully set [%s] as dcron leader", a.config.NodeName) + log.Printf("Successfully set [%s] as leader", a.config.NodeName) return true } return false } -// Checks if the dcron server member identified by key, is alive. +// Checks if the server member identified by key, is alive. func (a *AgentCommand) serverAlive(key string) bool { members := a.serf.Members() for _, member := range members { diff --git a/dcron/agent_test.go b/dkron/agent_test.go similarity index 96% rename from dcron/agent_test.go rename to dkron/agent_test.go index b382d96b0..e9c5db3f4 100644 --- a/dcron/agent_test.go +++ b/dkron/agent_test.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "testing" @@ -69,7 +69,7 @@ func TestAgentCommandElectLeader(t *testing.T) { } etcd := etcdc.NewClient([]string{}) - _, err := etcd.DeleteDir("dcron") + _, err := etcd.DeleteDir("dkron") if err != nil { if eerr, ok := err.(*etcdc.EtcdError); ok { if eerr.ErrorCode == etcdc.ErrCodeEtcdNotReachable { @@ -128,7 +128,7 @@ func TestAgentCommandElectLeader(t *testing.T) { stop := make(chan bool) time.Sleep(2 * time.Second) - go etcd.Watch("/dcron/leader", 0, false, receiver, stop) + go etcd.Watch("/dkron/leader", 0, false, receiver, stop) // Verify it runs "forever" select { @@ -158,7 +158,7 @@ func Test_processFilteredNodes(t *testing.T) { } etcd := etcdc.NewClient([]string{}) - _, err := etcd.DeleteDir("dcron") + _, err := etcd.DeleteDir("dkron") if err != nil { if eerr, ok := err.(*etcdc.EtcdError); ok { if eerr.ErrorCode == etcdc.ErrCodeEtcdNotReachable { diff --git a/dcron/api.go b/dkron/api.go similarity index 99% rename from dcron/api.go rename to dkron/api.go index b91f7f14a..5904ffec3 100644 --- a/dcron/api.go +++ b/dkron/api.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "encoding/json" diff --git a/dcron/api_test.go b/dkron/api_test.go similarity index 98% rename from dcron/api_test.go rename to dkron/api_test.go index f9d6a226c..788b5ca45 100644 --- a/dcron/api_test.go +++ b/dkron/api_test.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "bytes" diff --git a/dcron/config.go b/dkron/config.go similarity index 90% rename from dcron/config.go rename to dkron/config.go index 5a8d87833..87acf9da7 100644 --- a/dcron/config.go +++ b/dkron/config.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "encoding/base64" @@ -29,15 +29,16 @@ type Config struct { Server bool EncryptKey string StartJoin AppendSliceValue + Keyspace string } // This is the default port that we use for Serf communication const DefaultBindPort int = 7946 func init() { - viper.SetConfigName("dcron") // name of config file (without extension) - viper.AddConfigPath("/etc/dcron") // call multiple times to add many search paths - viper.AddConfigPath("$HOME/.dcron") // call multiple times to add many search paths + viper.SetConfigName("dkron") // name of config file (without extension) + viper.AddConfigPath("/etc/dkron") // call multiple times to add many search paths + viper.AddConfigPath("$HOME/.dkron") // call multiple times to add many search paths viper.AddConfigPath("./config") // call multiple times to add many search paths err := viper.ReadInConfig() // Find and read the config file if err != nil { // Handle errors reading the config file diff --git a/dcron/dashboard.go b/dkron/dashboard.go similarity index 99% rename from dcron/dashboard.go rename to dkron/dashboard.go index 49de37662..9b3301148 100644 --- a/dcron/dashboard.go +++ b/dkron/dashboard.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "encoding/json" diff --git a/dcron/etcd.go b/dkron/etcd.go similarity index 81% rename from dcron/etcd.go rename to dkron/etcd.go index c7d385caf..9aa4be73b 100644 --- a/dcron/etcd.go +++ b/dkron/etcd.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "encoding/json" @@ -9,11 +9,10 @@ import ( etcdc "github.com/coreos/go-etcd/etcd" ) -const keyspace = "/dcron" - type etcdClient struct { - Client *etcdc.Client - agent *AgentCommand + Client *etcdc.Client + agent *AgentCommand + keyspace string } // ServerStats encapsulates various statistics about an EtcdServer and its @@ -43,14 +42,14 @@ func init() { etcdc.SetLogger(stdlog.New(log.Writer(), "go-etcd", stdlog.LstdFlags)) } -func NewEtcdClient(machines []string, a *AgentCommand) *etcdClient { - return &etcdClient{Client: etcdc.NewClient(machines), agent: a} +func NewEtcdClient(machines []string, a *AgentCommand, keyspace string) *etcdClient { + return &etcdClient{Client: etcdc.NewClient(machines), agent: a, keyspace: keyspace} } func (e *etcdClient) SetJob(job *Job) error { jobJson, _ := json.Marshal(job) log.Debugf("Setting etcd key %s: %s", job.Name, string(jobJson)) - if _, err := e.Client.Set(keyspace+"/jobs/"+job.Name, string(jobJson), 0); err != nil { + if _, err := e.Client.Set(e.keyspace+"/jobs/"+job.Name, string(jobJson), 0); err != nil { return err } @@ -58,7 +57,7 @@ func (e *etcdClient) SetJob(job *Job) error { } func (e *etcdClient) GetJobs() ([]*Job, error) { - res, err := e.Client.Get(keyspace+"/jobs/", true, false) + res, err := e.Client.Get(e.keyspace+"/jobs/", true, false) if err != nil { eerr := err.(*etcdc.EtcdError) if eerr.ErrorCode == 100 { @@ -84,7 +83,7 @@ func (e *etcdClient) GetJobs() ([]*Job, error) { } func (e *etcdClient) GetJob(name string) (*Job, error) { - res, err := e.Client.Get(keyspace+"/jobs/"+name, false, false) + res, err := e.Client.Get(e.keyspace+"/jobs/"+name, false, false) if err != nil { return nil, err } @@ -99,7 +98,7 @@ func (e *etcdClient) GetJob(name string) (*Job, error) { } func (e *etcdClient) GetExecutions(jobName string) ([]*Execution, error) { - res, err := e.Client.Get(fmt.Sprintf("%s/executions/%s", keyspace, jobName), true, false) + res, err := e.Client.Get(fmt.Sprintf("%s/executions/%s", e.keyspace, jobName), true, false) if err != nil { return nil, err } @@ -122,7 +121,7 @@ func (e *etcdClient) SetExecution(execution *Execution) (string, error) { key := fmt.Sprintf("%d-%s", execution.StartedAt.UnixNano(), execution.NodeName) log.Debugf("Setting etcd key %s: %s", execution.JobName, string(eJson)) - res, err := e.Client.Set(fmt.Sprintf("%s/executions/%s/%s", keyspace, execution.JobName, key), string(eJson), 0) + res, err := e.Client.Set(fmt.Sprintf("%s/executions/%s/%s", e.keyspace, execution.JobName, key), string(eJson), 0) if err != nil { return "", err } @@ -131,7 +130,7 @@ func (e *etcdClient) SetExecution(execution *Execution) (string, error) { } func (e *etcdClient) GetLeader() string { - res, err := e.Client.Get(keyspace+"/leader", false, false) + res, err := e.Client.Get(e.keyspace+"/leader", false, false) if err != nil { if eerr, ok := err.(*etcdc.EtcdError); ok { if eerr.ErrorCode == etcdc.ErrCodeEtcdNotReachable { diff --git a/dcron/flag_slice_value.go b/dkron/flag_slice_value.go similarity index 96% rename from dcron/flag_slice_value.go rename to dkron/flag_slice_value.go index 09ea2246a..3a30155d0 100644 --- a/dcron/flag_slice_value.go +++ b/dkron/flag_slice_value.go @@ -1,4 +1,4 @@ -package dcron +package dkron import "strings" diff --git a/dcron/flag_slice_value_test.go b/dkron/flag_slice_value_test.go similarity index 97% rename from dcron/flag_slice_value_test.go rename to dkron/flag_slice_value_test.go index c8f03ef94..6e0e80cde 100644 --- a/dcron/flag_slice_value_test.go +++ b/dkron/flag_slice_value_test.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "flag" diff --git a/dcron/log.go b/dkron/log.go similarity index 92% rename from dcron/log.go rename to dkron/log.go index 1d28139c6..bcc703fb6 100644 --- a/dcron/log.go +++ b/dkron/log.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "github.com/Sirupsen/logrus" diff --git a/dcron/proc.go b/dkron/proc.go similarity index 99% rename from dcron/proc.go rename to dkron/proc.go index 3afd28cea..87da0ad3b 100644 --- a/dcron/proc.go +++ b/dkron/proc.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "encoding/json" diff --git a/dcron/scheduler.go b/dkron/scheduler.go similarity index 97% rename from dcron/scheduler.go rename to dkron/scheduler.go index 07cf0f933..f47e907b4 100644 --- a/dcron/scheduler.go +++ b/dkron/scheduler.go @@ -1,10 +1,10 @@ -package dcron +package dkron import ( "sync" "time" - "github.com/victorcoder/dcron/cron" + "github.com/victorcoder/dkron/cron" ) type Scheduler struct { diff --git a/dcron/scheduler_test.go b/dkron/scheduler_test.go similarity index 98% rename from dcron/scheduler_test.go rename to dkron/scheduler_test.go index 85f8f7936..b6a37094e 100644 --- a/dcron/scheduler_test.go +++ b/dkron/scheduler_test.go @@ -1,4 +1,4 @@ -package dcron +package dkron import ( "testing" diff --git a/dcron_theme/base.html b/dkron_theme/base.html similarity index 94% rename from dcron_theme/base.html rename to dkron_theme/base.html index d3740fe4f..6d05bc852 100644 --- a/dcron_theme/base.html +++ b/dkron_theme/base.html @@ -48,16 +48,16 @@

Job scheduling made easy, distributed and highly-available

- Download + Download
- +
-

Dcron is a system service that runs scheduled jobs at given intervals or times, just like the cron unix service but distributed in several machines in a cluster. If a machine fails (the leader), a follower will take over and keep running the scheduled jobs without human intervention. Dcron is Open Source and freely available.

+

Dkron is a system service that runs scheduled jobs at given intervals or times, just like the cron unix service but distributed in several machines in a cluster. If a machine fails (the leader), a follower will take over and keep running the scheduled jobs without human intervention. Dkron is Open Source and freely available.

@@ -120,7 +120,7 @@

Example use cases