Renaming: "tags" -> "commands"; "commands" -> "actions"

devel
KatolaZ 8 years ago
parent 096b3fd286
commit b31fe15e0d
  1. 48
      commits.go
  2. 6
      config.go
  3. 4
      examples/scorsh_example.cfg
  4. 12
      examples/worker1/worker1.cfg
  5. 10
      examples/worker2/worker2.cfg
  6. 28
      exec.go
  7. 10
      scorshd.go
  8. 2
      spooler.go
  9. 42
      types.go
  10. 33
      workers.go

@ -96,10 +96,10 @@ func intersectKeys(ref map[string]bool, keys []string) []string {
return ret return ret
} }
func findTagConfig(tagName string, w *worker) (*commandCfg, bool) { func findCmdConfig(cmdName string, w *worker) (*commandCfg, bool) {
for _, c := range w.Tags { for _, c := range w.Commands {
if c.Name == tagName { if c.Name == cmdName {
return &c, true return &c, true
} }
} }
@ -123,7 +123,7 @@ func getCommitterEmail(c *git.Commit) string {
// looking for scorsh commands, and tries to execute those if found // looking for scorsh commands, and tries to execute those if found
func walkCommits(msg spoolMsg, w *worker) error { func walkCommits(msg spoolMsg, w *worker) error {
var commands *clientMsg var cmdMsg *clientMsg
debug.log("[worker: %s] Inside walkCommits\n", w.Name) debug.log("[worker: %s] Inside walkCommits\n", w.Name)
@ -135,7 +135,7 @@ func walkCommits(msg spoolMsg, w *worker) error {
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error while opening repository %s (%s)\n", fmt.Fprintf(os.Stderr, "Error while opening repository %s (%s)\n",
reponame, err) reponame, err)
return SCORSHerr(SCORSH_ERR_NO_REPO) return SCORSHerr(errNoRepo)
} }
oldRevOid, _ := git.NewOid(oldRev) oldRevOid, _ := git.NewOid(oldRev)
@ -143,7 +143,7 @@ func walkCommits(msg spoolMsg, w *worker) error {
oldrevCommit, err := repo.LookupCommit(oldRevOid) oldrevCommit, err := repo.LookupCommit(oldRevOid)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", oldRev) fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", oldRev)
return SCORSHerr(SCORSH_ERR_NO_COMMIT) return SCORSHerr(errNoCommit)
} }
newRevOid, _ := git.NewOid(newRev) newRevOid, _ := git.NewOid(newRev)
@ -151,7 +151,7 @@ func walkCommits(msg spoolMsg, w *worker) error {
newrevCommit, err := repo.LookupCommit(newRevOid) newrevCommit, err := repo.LookupCommit(newRevOid)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", newRev) fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", newRev)
return SCORSHerr(SCORSH_ERR_NO_COMMIT) return SCORSHerr(errNoCommit)
} }
curCommit := newrevCommit curCommit := newrevCommit
@ -167,39 +167,39 @@ func walkCommits(msg spoolMsg, w *worker) error {
// that specific scorsh-command // that specific scorsh-command
// Check if the commit contains a scorsh command // Check if the commit contains a scorsh command
commands, err = findScorshMessage(commit) cmdMsg, err = findScorshMessage(commit)
if err == nil { if err == nil {
// the commit contains a valid scorsh message // the commit contains a valid scorsh message
// 1) get the list of all the keyrings which verify the message // 1) get the list of all the keyrings which verify the message
validKeys := getValidKeys(commit, &(w.Keys)) validKeys := getValidKeys(commit, &(w.Keys))
debug.log("[worker: %s] validated keyrings on commit: %s\n", w.Name, validKeys) debug.log("[worker: %s] validated keyrings on commit: %s\n", w.Name, validKeys)
// 2) then for each tag in the message // 2) then for each command in the message
for _, t := range commands.Tags { for _, c := range cmdMsg.Commands {
// a) check that the tag is among those accepted by the worker // a) check that the command is among those accepted by the worker
tagCfg, goodTag := findTagConfig(t.Tag, w) cmdCfg, goodCmd := findCmdConfig(c.Cmd, w)
debug.log("[worker: %s] goodTag: %s\n", w.Name, goodTag) debug.log("[worker: %s] goodCmd: %s\n", w.Name, goodCmd)
if !goodTag { if !goodCmd {
debug.log("[worker: %s] unsupported tag: %s\n", w.Name, t.Tag) debug.log("[worker: %s] unsupported command: %s\n", w.Name, c.Cmd)
continue continue
} }
// b) check that at least one of the accepted tag keyrings // b) check that at least one of the accepted command keyrings
// is in valid_keys // is in valid_keys
goodKeys := intersectKeys(w.TagKeys[t.Tag], validKeys) != nil goodKeys := intersectKeys(w.CommandKeys[c.Cmd], validKeys) != nil
debug.log("[worker: %s] goodKeys: %s\n", w.Name, goodKeys) debug.log("[worker: %s] goodKeys: %s\n", w.Name, goodKeys)
if !goodKeys { if !goodKeys {
debug.log("[worker: %s] no matching keys for tag: %s\n", w.Name, t.Tag) debug.log("[worker: %s] no matching keys for command: %s\n", w.Name, c.Cmd)
continue continue
} }
// c) If everything is OK, execute the tag // c) If everything is OK, execute the command
if goodTag && goodKeys { if goodCmd && goodKeys {
env := setEnvironment(&msg, t.Tag, getAuthorEmail(commit), getCommitterEmail(commit)) env := setEnvironment(&msg, c.Cmd, getAuthorEmail(commit), getCommitterEmail(commit))
errs := execTag(tagCfg, t.Args, env) errs := execCommand(cmdCfg, c.Args, env)
debug.log("[worker: %s] errors in tag %s: %s\n", w.Name, t.Tag, errs) debug.log("[worker: %s] errors in command %s: %s\n", w.Name, c.Cmd, errs)
} }
} }
} else { } else {
@ -209,7 +209,7 @@ func walkCommits(msg spoolMsg, w *worker) error {
curCommit = commit.Parent(0) curCommit = commit.Parent(0)
} else { } else {
fmt.Printf("Commit %x not found!\n", curCommit.Id()) fmt.Printf("Commit %x not found!\n", curCommit.Id())
return SCORSHerr(SCORSH_ERR_NO_COMMIT) return SCORSHerr(errNoCommit)
} }
} }
return nil return nil

@ -27,10 +27,10 @@ func readGlobalConfig(fname string) *master {
//fmt.Printf("%s", cfg) //fmt.Printf("%s", cfg)
if cfg.Logfile != "" { if cfg.LogFile != "" {
f, err := os.OpenFile(cfg.Logfile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0600) f, err := os.OpenFile(cfg.LogFile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0600)
if err != nil { if err != nil {
log.Fatal("Error opening logfile: ", cfg.Logfile, err) log.Fatal("Error opening logfile: ", cfg.LogFile, err)
} else { } else {
log.SetOutput(io.Writer(f)) log.SetOutput(io.Writer(f))
} }

@ -10,14 +10,14 @@ s_workers:
w_repos: [".*:.*"], # All branches in all repos w_repos: [".*:.*"], # All branches in all repos
w_folder: ./worker1, w_folder: ./worker1,
w_logfile: ./worker1/worker1.log, w_logfile: ./worker1/worker1.log,
w_tagfile: "./worker1/worker1.cfg", w_cfgfile: "./worker1/worker1.cfg",
}, },
{ {
w_name: worker2, w_name: worker2,
w_repos: [".*:master"], # Branch master in all repos w_repos: [".*:master"], # Branch master in all repos
w_folder: ./worker2, w_folder: ./worker2,
w_logfile: ./worker2/worker2.log, w_logfile: ./worker2/worker2.log,
w_tagfile: "./worker2/worker2.cfg", w_cfgfile: "./worker2/worker2.cfg",
} }
] ]
... ...

@ -8,24 +8,24 @@
--- ---
w_tags: w_commands:
[ [
{ {
t_name: "LOG", t_name: "LOG",
t_keyrings: ["allowed_users.asc"], t_keyrings: ["allowed_users.asc"],
t_commands: [ t_actions: [
{ {
c_url: "file:///home/katolaz/bin/scorsh_script.sh" a_url: "file:///home/katolaz/bin/scorsh_script.sh"
## c_hash: "12da324fb76s924acbce" ## a_hash: "12da324fb76s924acbce"
} }
] ]
}, },
{ {
t_name: "build", t_name: "build",
t_keyrings: ["allowed_users.asc"], t_keyrings: ["allowed_users.asc"],
t_commands: [ t_actions: [
{ {
c_url: "file:///home/katolaz/bin/scorsh_script.sh" a_url: "file:///home/katolaz/bin/scorsh_script.sh"
} }
] ]
} }

@ -1,21 +1,21 @@
--- ---
w_tags: w_commands:
[ [
{ {
t_name: "DEPLOY", t_name: "DEPLOY",
t_keyrings: ["allowed_users.asc"], t_keyrings: ["allowed_users.asc"],
t_commands: [ t_actions: [
{ {
c_url: "file:///home/katolaz/bin/deploy.sh" a_url: "file:///home/katolaz/bin/deploy.sh"
} }
] ]
}, },
{ {
t_name: "build", t_name: "build",
t_keyrings: ["allowed_users.asc"], t_keyrings: ["allowed_users.asc"],
t_commands: [ t_actions: [
{ {
c_url: "file:///home/katolaz/bin/scorsh_build.sh" a_url: "file:///home/katolaz/bin/scorsh_build.sh"
} }
] ]
} }

@ -55,34 +55,34 @@ func execURL(cmdURL *url.URL, args, env []string) error {
return nil return nil
} }
func execTag(tag *commandCfg, args []string, env []string) []error { func execCommand(cmd *commandCfg, args []string, env []string) []error {
var ret []error var ret []error
for _, c := range tag.Commands { for _, a := range cmd.Actions {
debug.log("[tag: %s] attempting command: %s\n", tag.Name, c.URL) debug.log("[command: %s] attempting action: %s\n", cmd.Name, a.URL)
cmdURL, err := url.Parse(c.URL) actionURL, err := url.Parse(a.URL)
if err != nil { if err != nil {
log.Printf("[tag: %s] error parsing URL: %s", tag.Name, err) log.Printf("[command: %s] error parsing URL: %s", cmd.Name, err)
} else { } else {
if cmdURL.Scheme == "file" { if actionURL.Scheme == "file" {
err = nil err = nil
// if a hash is specified, check that it matches // if a hash is specified, check that it matches
if c.Hash != "" { if a.Hash != "" {
err = checkHash(cmdURL.Path, c.Hash) err = checkHash(actionURL.Path, a.Hash)
} }
// if the hash does not match, abort the command // if the hash does not match, abort the command
if err != nil { if err != nil {
log.Printf("[tag: %s] %s -- aborting command\n", tag.Name, err) log.Printf("[command: %s] %s -- aborting action\n", cmd.Name, err)
ret = append(ret, err) ret = append(ret, err)
continue continue
} else { } else {
// finally, the command can be executed // finally, the command can be executed
err = execLocalFile(cmdURL, args, env) err = execLocalFile(actionURL, args, env)
} }
} else if cmdURL.Scheme == "http" || cmdURL.Scheme == "https" { } else if actionURL.Scheme == "http" || actionURL.Scheme == "https" {
err = execURL(cmdURL, args, env) err = execURL(actionURL, args, env)
} }
} }
ret = append(ret, err) ret = append(ret, err)
@ -90,7 +90,7 @@ func execTag(tag *commandCfg, args []string, env []string) []error {
return ret return ret
} }
func setEnvironment(msg *spoolMsg, tag, author, committer string) []string { func setEnvironment(msg *spoolMsg, cmd, author, committer string) []string {
env := os.Environ() env := os.Environ()
env = append(env, fmt.Sprintf("SCORSH_REPO=%s", msg.Repo)) env = append(env, fmt.Sprintf("SCORSH_REPO=%s", msg.Repo))
@ -98,7 +98,7 @@ func setEnvironment(msg *spoolMsg, tag, author, committer string) []string {
env = append(env, fmt.Sprintf("SCORSH_OLDREV=%s", msg.OldRev)) env = append(env, fmt.Sprintf("SCORSH_OLDREV=%s", msg.OldRev))
env = append(env, fmt.Sprintf("SCORSH_NEWREV=%s", msg.NewRev)) env = append(env, fmt.Sprintf("SCORSH_NEWREV=%s", msg.NewRev))
env = append(env, fmt.Sprintf("SCORSH_ID=%s", msg.ID)) env = append(env, fmt.Sprintf("SCORSH_ID=%s", msg.ID))
env = append(env, fmt.Sprintf("SCORSH_TAG=%s", tag)) env = append(env, fmt.Sprintf("SCORSH_COMMAND=%s", cmd))
env = append(env, fmt.Sprintf("SCORSH_AUTHOR=%s", author)) env = append(env, fmt.Sprintf("SCORSH_AUTHOR=%s", author))
env = append(env, fmt.Sprintf("SCORSH_COMMITTER=%s", committer)) env = append(env, fmt.Sprintf("SCORSH_COMMITTER=%s", committer))

@ -29,15 +29,15 @@ func SCORSHerr(err int) error {
var errStr string var errStr string
switch err { switch err {
case SCORSH_ERR_NO_FILE: case errNoFile:
errStr = "Invalid file name" errStr = "Invalid file name"
case SCORSH_ERR_KEYRING: case errKeyring:
errStr = "Invalid keyring" errStr = "Invalid keyring"
case SCORSH_ERR_NO_REPO: case errNoRepo:
errStr = "Invalid repository" errStr = "Invalid repository"
case SCORSH_ERR_NO_COMMIT: case errNoCommit:
errStr = "Invalid commit ID" errStr = "Invalid commit ID"
case SCORSH_ERR_SIGNATURE: case errSignature:
errStr = "Invalid signature" errStr = "Invalid signature"
default: default:
errStr = "Generic Error" errStr = "Generic Error"

@ -18,7 +18,7 @@ func parseRequest(fname string, msg *spoolMsg) error {
data, err := ioutil.ReadFile(fname) data, err := ioutil.ReadFile(fname)
if err != nil { if err != nil {
log.Printf("Unable to open file: %s\n", fname) log.Printf("Unable to open file: %s\n", fname)
return SCORSHerr(SCORSH_ERR_NO_FILE) return SCORSHerr(errNoFile)
} }
debug.log("[parseRequest] file contains: \n%s\n", data) debug.log("[parseRequest] file contains: \n%s\n", data)

@ -8,11 +8,11 @@ import (
// error constants // error constants
const ( const (
SCORSH_ERR_NO_FILE = -(1 << iota) errNoFile = -(1 << iota)
SCORSH_ERR_KEYRING errKeyring
SCORSH_ERR_NO_REPO errNoRepo
SCORSH_ERR_NO_COMMIT errNoCommit
SCORSH_ERR_SIGNATURE errSignature
) )
// spoolMsg type represents messages received from the spool and // spoolMsg type represents messages received from the spool and
@ -28,15 +28,15 @@ type spoolMsg struct {
// An action represents a script of a command configured on the server side // An action represents a script of a command configured on the server side
type action struct { type action struct {
URL string `yaml:"c_url"` URL string `yaml:"a_url"`
Hash string `yaml:"c_hash"` Hash string `yaml:"a_hash"`
} }
// commandCfg represents a command configured on the server side // commandCfg represents a command configured on the server side
type commandCfg struct { type commandCfg struct {
Name string `yaml:"t_name"` Name string `yaml:"t_name"`
Keyrings []string `yaml:"t_keyrings"` Keyrings []string `yaml:"t_keyrings"`
Commands []action `yaml:"t_commands"` Actions []action `yaml:"t_actions"`
} }
// workerCfg represents the static configuration of a worker // workerCfg represents the static configuration of a worker
@ -44,11 +44,11 @@ type workerCfg struct {
Name string `yaml:"w_name"` Name string `yaml:"w_name"`
Repos []string `yaml:"w_repos"` Repos []string `yaml:"w_repos"`
Folder string `yaml:"w_folder"` Folder string `yaml:"w_folder"`
Logfile string `yaml:"w_logfile"` LogFile string `yaml:"w_logfile"`
Tagfile string `yaml:"w_tagfile"` CfgFile string `yaml:"w_cfgfile"`
// Keyrings []string `yaml:"w_keyrings"` // Keyrings []string `yaml:"w_keyrings"`
Tags []commandCfg `yaml:"w_tags"` Commands []commandCfg `yaml:"w_commands"`
TagKeys map[string]map[string]bool CommandKeys map[string]map[string]bool
} }
// workerState represents the runtime state of a worker // workerState represents the runtime state of a worker
@ -67,7 +67,7 @@ type worker struct {
// masterCfg represents the static configuration of the master // masterCfg represents the static configuration of the master
type masterCfg struct { type masterCfg struct {
Spooldir string `yaml:"s_spooldir"` Spooldir string `yaml:"s_spooldir"`
Logfile string `yaml:"s_logfile"` LogFile string `yaml:"s_logfile"`
LogPrefix string `yaml:"s_logprefix"` LogPrefix string `yaml:"s_logprefix"`
Workers []worker `yaml:"s_workers"` Workers []worker `yaml:"s_workers"`
} }
@ -88,13 +88,13 @@ type master struct {
// clientCmd is the type of commands sent by clients // clientCmd is the type of commands sent by clients
type clientCmd struct { type clientCmd struct {
Tag string `yaml:"s_tag"` Cmd string `yaml:"s_cmd"`
Args []string `yaml:"s_args"` Args []string `yaml:"s_args"`
} }
// clientMsg is the list of commands sent by a client // clientMsg is the list of commands sent by a client
type clientMsg struct { type clientMsg struct {
Tags []clientCmd `yaml:"scorsh"` Commands []clientCmd `yaml:"scorsh"`
} }
//////////////////////// ////////////////////////
@ -104,7 +104,7 @@ func (cfg *master) String() string {
var buff bytes.Buffer var buff bytes.Buffer
fmt.Fprintf(&buff, "spooldir: %s\n", cfg.Spooldir) fmt.Fprintf(&buff, "spooldir: %s\n", cfg.Spooldir)
fmt.Fprintf(&buff, "logfile: %s\n", cfg.Logfile) fmt.Fprintf(&buff, "logfile: %s\n", cfg.LogFile)
fmt.Fprintf(&buff, "logprefix: %s\n", cfg.LogPrefix) fmt.Fprintf(&buff, "logprefix: %s\n", cfg.LogPrefix)
fmt.Fprintf(&buff, "Workers: \n") fmt.Fprintf(&buff, "Workers: \n")
@ -135,8 +135,8 @@ func (w *worker) String() string {
fmt.Fprintf(&buff, "Name: %s\n", w.Name) fmt.Fprintf(&buff, "Name: %s\n", w.Name)
fmt.Fprintf(&buff, "Repos: %s\n", w.Repos) fmt.Fprintf(&buff, "Repos: %s\n", w.Repos)
fmt.Fprintf(&buff, "Folder: %s\n", w.Folder) fmt.Fprintf(&buff, "Folder: %s\n", w.Folder)
fmt.Fprintf(&buff, "Logfile: %s\n", w.Logfile) fmt.Fprintf(&buff, "LogFile: %s\n", w.LogFile)
fmt.Fprintf(&buff, "Tagfile: %s\n", w.Tagfile) fmt.Fprintf(&buff, "CfgFile: %s\n", w.CfgFile)
// fmt.Fprintf(&buff, "Keyrings: %s\n", w.Keyrings) // fmt.Fprintf(&buff, "Keyrings: %s\n", w.Keyrings)
return buff.String() return buff.String()
@ -146,10 +146,10 @@ func (msg *clientMsg) String() string {
var buff bytes.Buffer var buff bytes.Buffer
for _, t := range msg.Tags { for _, c := range msg.Commands {
fmt.Fprintf(&buff, "s_tag: %s\n", t.Tag) fmt.Fprintf(&buff, "s_cmd: %s\n", c.Cmd)
for _, a := range t.Args { for _, a := range c.Args {
fmt.Fprintf(&buff, " s_args: %s\n", a) fmt.Fprintf(&buff, " s_args: %s\n", a)
} }
} }

@ -35,16 +35,16 @@ func (w *worker) Matches(repo, branch string) bool {
func (w *worker) LoadKeyrings() error { func (w *worker) LoadKeyrings() error {
w.Keys = make(map[string]openpgp.KeyRing) w.Keys = make(map[string]openpgp.KeyRing)
w.TagKeys = make(map[string]map[string]bool) w.CommandKeys = make(map[string]map[string]bool)
for _, t := range w.Tags { for _, c := range w.Commands {
w.TagKeys[t.Name] = make(map[string]bool) w.CommandKeys[c.Name] = make(map[string]bool)
// Open the keyring files // Open the keyring files
for _, keyring := range t.Keyrings { for _, keyring := range c.Keyrings {
if _, ok := w.Keys[keyring]; ok { if _, ok := w.Keys[keyring]; ok {
// keyring has been loaded: just add it to the TagKeys map // keyring has been loaded: just add it to the CommandKeys map
w.TagKeys[t.Name][keyring] = true w.CommandKeys[c.Name][keyring] = true
continue continue
} }
kfile := fmt.Sprintf("%s/%s", w.Folder, keyring) kfile := fmt.Sprintf("%s/%s", w.Folder, keyring)
@ -64,26 +64,25 @@ func (w *worker) LoadKeyrings() error {
//return fmt.Errorf("Unable to load keyring: ", err_key) //return fmt.Errorf("Unable to load keyring: ", err_key)
} }
w.Keys[keyring] = kr w.Keys[keyring] = kr
w.TagKeys[t.Name][keyring] = true w.CommandKeys[c.Name][keyring] = true
_ = f.Close() _ = f.Close()
} }
} }
return nil return nil
} }
// LoadTags loads all the configured commands for the worker // LoadCommands loads all the configured commands for the worker
func (w *worker) LoadTags() error { func (w *worker) LoadCommands() error {
wTags, err := ioutil.ReadFile(w.Tagfile) wCmds, err := ioutil.ReadFile(w.CfgFile)
if err != nil { if err != nil {
return fmt.Errorf("Cannot read worker config: %s", err) return fmt.Errorf("Cannot read worker config: %s", err)
} }
err = yaml.Unmarshal(wTags, w) err = yaml.Unmarshal(wCmds, w)
//err = yaml.Unmarshal(w_tags, tags)
if err != nil { if err != nil {
return fmt.Errorf("Error while reading tags: %s", err) return fmt.Errorf("Error while reading commands: %s", err)
} }
return nil return nil
@ -132,14 +131,14 @@ func startWorkers(master *master) error {
worker.StatusChan = master.StatusChan worker.StatusChan = master.StatusChan
worker.MsgChan = make(chan spoolMsg, 10) worker.MsgChan = make(chan spoolMsg, 10)
// Load worker tags from worker.Tagfile // Load worker commands from worker.CfgFile
err := worker.LoadTags() err := worker.LoadCommands()
if err != nil { if err != nil {
close(worker.MsgChan) close(worker.MsgChan)
return fmt.Errorf("[Starting worker: %s] Unable to load tags: %s", worker.Name, err) return fmt.Errorf("[Starting worker: %s] Unable to load commands: %s", worker.Name, err)
} }
// Load worker keyrings -- this must be called *after* LoadTags!!!! // Load worker keyrings -- this must be called *after* LoadCommands!!!!
err = worker.LoadKeyrings() err = worker.LoadKeyrings()
if err != nil { if err != nil {
close(worker.MsgChan) close(worker.MsgChan)

Loading…
Cancel
Save