diff options
author | KatolaZ <katolaz@freaknet.org> | 2017-08-07 09:55:35 +0100 |
---|---|---|
committer | KatolaZ <katolaz@freaknet.org> | 2017-08-07 09:55:35 +0100 |
commit | 096b3fd2867d7bb2d3cd1f85d8806c651b26d625 (patch) | |
tree | 4dfcc77e86cc0e667c14a92c43d1785b4cb5e4b8 | |
parent | 802d703f617036ec1d18aa8ecb9678ca3390f68a (diff) | |
parent | d3105e671a19fec1060652531ce783227fb9fab6 (diff) |
Merge branch 'devel'
-rw-r--r-- | commits.go | 106 | ||||
-rw-r--r-- | config.go | 4 | ||||
-rw-r--r-- | exec.go | 4 | ||||
-rw-r--r-- | scorshd.go | 14 | ||||
-rw-r--r-- | spooler.go | 8 | ||||
-rw-r--r-- | types.go | 88 | ||||
-rw-r--r-- | workers.go | 16 |
7 files changed, 121 insertions, 119 deletions
@@ -41,8 +41,9 @@ func checkSignature(commit *git.Commit, keyring *openpgp.KeyRing) (signature, si return "", "", err } -func findScorshMessage(commit *git.Commit) (string, error) { +func findScorshMessage(commit *git.Commit) (*clientMsg, error) { + var commands = new(clientMsg) sep := "---\n" msg := commit.RawMessage() @@ -52,9 +53,20 @@ func findScorshMessage(commit *git.Commit) (string, error) { idx := strings.Index(msg, sep) if idx < 0 { - return "", fmt.Errorf("no SCORSH message found") + return nil, fmt.Errorf("no SCORSH message found") } - return msg[idx:], nil + + err := yaml.Unmarshal([]byte(msg[idx:]), &commands) + + if err != nil { + // no scorsh message found + err = fmt.Errorf("unmarshal error: %s", err) + commands = nil + } else { + err = nil + } + + return commands, nil } // return a list of keyring names which verify the signature of a given commit @@ -84,7 +96,7 @@ func intersectKeys(ref map[string]bool, keys []string) []string { return ret } -func findTagConfig(tagName string, w *SCORSHworker) (*SCORSHtagCfg, bool) { +func findTagConfig(tagName string, w *worker) (*commandCfg, bool) { for _, c := range w.Tags { if c.Name == tagName { @@ -107,12 +119,11 @@ func getCommitterEmail(c *git.Commit) string { } -// walk_commits traverses all the commits between two references, +// walkCommits traverses all the commits between two references, // looking for scorsh commands, and tries to execute those if found -func walkCommits(msg SCORSHmsg, w *SCORSHworker) error { +func walkCommits(msg spoolMsg, w *worker) error { - var tags SCORSHclientMsg - var commitMsg string + var commands *clientMsg debug.log("[worker: %s] Inside walkCommits\n", w.Name) @@ -151,53 +162,44 @@ func walkCommits(msg SCORSHmsg, w *SCORSHworker) error { commit, err := repo.LookupCommit(curCommit.Id()) if err == nil { - // We look for scorsh-tags, and if the commit has any, check if - // it can be verified by any of the keyrings associated with - // that specific scorsh-tag + // We look for scorsh-commands, and if the commit has any, check + // if it can be verified by any of the keyrings associated with + // that specific scorsh-command // Check if the commit contains a scorsh command - commitMsg, err = findScorshMessage(commit) + commands, err = findScorshMessage(commit) if err == nil { - // Check if is the comment contains a valid scorsh message - err = yaml.Unmarshal([]byte(commitMsg), &tags) - - if err != nil { - // no scorsh message found - err = fmt.Errorf("unmarshal error: %s", err) - } else { - // there is a scorsh message there so.... - - // 1) get the list of all the keyrings which verify the message - validKeys := getValidKeys(commit, &(w.Keys)) - debug.log("[worker: %s] validated keyrings on commit: %s\n", w.Name, validKeys) - - // 2) then for each tag in the message - for _, t := range tags.Tags { - // a) check that the tag is among those accepted by the worker - tagCfg, goodTag := findTagConfig(t.Tag, w) - debug.log("[worker: %s] goodTag: %s\n", w.Name, goodTag) - - if !goodTag { - debug.log("[worker: %s] unsupported tag: %s\n", w.Name, t.Tag) - continue - } - - // b) check that at least one of the accepted tag keyrings - // is in valid_keys - goodKeys := intersectKeys(w.TagKeys[t.Tag], validKeys) != nil - debug.log("[worker: %s] goodKeys: %s\n", w.Name, goodKeys) - - if !goodKeys { - debug.log("[worker: %s] no matching keys for tag: %s\n", w.Name, t.Tag) - continue - } - - // c) If everything is OK, execute the tag - if goodTag && goodKeys { - env := setEnvironment(&msg, t.Tag, getAuthorEmail(commit), getCommitterEmail(commit)) - errs := execTag(tagCfg, t.Args, env) - debug.log("[worker: %s] errors in tag %s: %s\n", w.Name, t.Tag, errs) - } + // the commit contains a valid scorsh message + // 1) get the list of all the keyrings which verify the message + validKeys := getValidKeys(commit, &(w.Keys)) + debug.log("[worker: %s] validated keyrings on commit: %s\n", w.Name, validKeys) + + // 2) then for each tag in the message + for _, t := range commands.Tags { + // a) check that the tag is among those accepted by the worker + tagCfg, goodTag := findTagConfig(t.Tag, w) + debug.log("[worker: %s] goodTag: %s\n", w.Name, goodTag) + + if !goodTag { + debug.log("[worker: %s] unsupported tag: %s\n", w.Name, t.Tag) + continue + } + + // b) check that at least one of the accepted tag keyrings + // is in valid_keys + goodKeys := intersectKeys(w.TagKeys[t.Tag], validKeys) != nil + debug.log("[worker: %s] goodKeys: %s\n", w.Name, goodKeys) + + if !goodKeys { + debug.log("[worker: %s] no matching keys for tag: %s\n", w.Name, t.Tag) + continue + } + + // c) If everything is OK, execute the tag + if goodTag && goodKeys { + env := setEnvironment(&msg, t.Tag, getAuthorEmail(commit), getCommitterEmail(commit)) + errs := execTag(tagCfg, t.Args, env) + debug.log("[worker: %s] errors in tag %s: %s\n", w.Name, t.Tag, errs) } } } else { @@ -10,14 +10,14 @@ import ( // Read a configuration from fname or die -func readGlobalConfig(fname string) *SCORSHmaster { +func readGlobalConfig(fname string) *master { data, err := ioutil.ReadFile(fname) if err != nil { log.Fatal("Error while reading file: ", err) } - var cfg = new(SCORSHmaster) + var cfg = new(master) // Unmarshal the YAML configuration file into a SCORSHcfg structure err = yaml.Unmarshal(data, cfg) @@ -55,7 +55,7 @@ func execURL(cmdURL *url.URL, args, env []string) error { return nil } -func execTag(tag *SCORSHtagCfg, args []string, env []string) []error { +func execTag(tag *commandCfg, args []string, env []string) []error { var ret []error @@ -90,7 +90,7 @@ func execTag(tag *SCORSHtagCfg, args []string, env []string) []error { return ret } -func setEnvironment(msg *SCORSHmsg, tag, author, committer string) []string { +func setEnvironment(msg *spoolMsg, tag, author, committer string) []string { env := os.Environ() env = append(env, fmt.Sprintf("SCORSH_REPO=%s", msg.Repo)) @@ -46,9 +46,9 @@ func SCORSHerr(err int) error { } -func findMatchingWorkers(master *SCORSHmaster, msg *SCORSHmsg) []*SCORSHworker { +func findMatchingWorkers(master *master, msg *spoolMsg) []*worker { - var ret []*SCORSHworker + var ret []*worker for idx, w := range master.Workers { if w.Matches(msg.Repo, msg.Branch) { @@ -59,7 +59,7 @@ func findMatchingWorkers(master *SCORSHmaster, msg *SCORSHmsg) []*SCORSHworker { return ret } -func runMaster(master *SCORSHmaster) { +func runMaster(master *master) { // master main loop: @@ -108,16 +108,16 @@ func runMaster(master *SCORSHmaster) { debug.log("[master] Exiting the for loop, for some mysterious reason...\n") } -func initMaster() *SCORSHmaster { +func initMaster() *master { master := readGlobalConfig(*confFile) - master.Repos = make(map[string][]*SCORSHworker) + master.Repos = make(map[string][]*worker) master.WorkingMsg = make(map[string]int) // This is the channel on which we receive acks from workers - master.StatusChan = make(chan SCORSHmsg) + master.StatusChan = make(chan spoolMsg) // This is the channel on which we exchange messages with the spooler - master.Spooler = make(chan SCORSHmsg) + master.Spooler = make(chan spoolMsg) debug.log("[InitMaster] StatusChan: %s\n", master.StatusChan) @@ -11,7 +11,7 @@ import ( ) // parse a request file and return a SCORSHmessage -func parseRequest(fname string, msg *SCORSHmsg) error { +func parseRequest(fname string, msg *spoolMsg) error { debug.log("[parseRequest] message at start: %s\n", msg) @@ -33,7 +33,7 @@ func parseRequest(fname string, msg *SCORSHmsg) error { return nil } -func spooler(watcher *fsnotify.Watcher, master chan SCORSHmsg) { +func spooler(watcher *fsnotify.Watcher, master chan spoolMsg) { log.Println("Spooler started correctly") @@ -44,7 +44,7 @@ func spooler(watcher *fsnotify.Watcher, master chan SCORSHmsg) { // "Write" event, which should happen only when the file is // created if event.Op == fsnotify.Write { - var msg SCORSHmsg + var msg spoolMsg debug.log("[spooler] new file %s detected\n", event.Name) err := parseRequest(event.Name, &msg) if err != nil { @@ -71,7 +71,7 @@ func spooler(watcher *fsnotify.Watcher, master chan SCORSHmsg) { } } -func startSpooler(master *SCORSHmaster) error { +func startSpooler(master *master) error { watcher, err := fsnotify.NewWatcher() @@ -15,9 +15,9 @@ const ( SCORSH_ERR_SIGNATURE ) -// SCORSHmsg type represents messages received from the spool and +// spoolMsg type represents messages received from the spool and // sent to workers -type SCORSHmsg struct { +type spoolMsg struct { ID string `yaml:"m_id"` Repo string `yaml:"m_repo"` Branch string `yaml:"m_branch"` @@ -26,80 +26,80 @@ type SCORSHmsg struct { Path string } -// SCORSHcmd represents commands configured on the server side -type SCORSHcmd struct { +// An action represents a script of a command configured on the server side +type action struct { URL string `yaml:"c_url"` Hash string `yaml:"c_hash"` } -// SCORSHtagCfg represents tags configured on the server side -type SCORSHtagCfg struct { - Name string `yaml:"t_name"` - Keyrings []string `yaml:"t_keyrings"` - Commands []SCORSHcmd `yaml:"t_commands"` +// commandCfg represents a command configured on the server side +type commandCfg struct { + Name string `yaml:"t_name"` + Keyrings []string `yaml:"t_keyrings"` + Commands []action `yaml:"t_commands"` } -// SCORSHworkerCfg represents the static configuration of a worker -type SCORSHworkerCfg struct { +// workerCfg represents the static configuration of a worker +type workerCfg struct { Name string `yaml:"w_name"` Repos []string `yaml:"w_repos"` Folder string `yaml:"w_folder"` Logfile string `yaml:"w_logfile"` Tagfile string `yaml:"w_tagfile"` // Keyrings []string `yaml:"w_keyrings"` - Tags []SCORSHtagCfg `yaml:"w_tags"` + Tags []commandCfg `yaml:"w_tags"` TagKeys map[string]map[string]bool } -// SCORSHworkerState represents the runtime state of a worker -type SCORSHworkerState struct { +// workerState represents the runtime state of a worker +type workerState struct { Keys map[string]openpgp.KeyRing - MsgChan chan SCORSHmsg - StatusChan chan SCORSHmsg + MsgChan chan spoolMsg + StatusChan chan spoolMsg } -// SCORSHworker represents the configuration and state of a worker -type SCORSHworker struct { - SCORSHworkerCfg `yaml:",inline"` - SCORSHworkerState +// worker represents the configuration and state of a worker +type worker struct { + workerCfg `yaml:",inline"` + workerState } -// SCORSHmasterCfg represents the static configuration of the master -type SCORSHmasterCfg struct { - Spooldir string `yaml:"s_spooldir"` - Logfile string `yaml:"s_logfile"` - LogPrefix string `yaml:"s_logprefix"` - Workers []SCORSHworker `yaml:"s_workers"` +// masterCfg represents the static configuration of the master +type masterCfg struct { + Spooldir string `yaml:"s_spooldir"` + Logfile string `yaml:"s_logfile"` + LogPrefix string `yaml:"s_logprefix"` + Workers []worker `yaml:"s_workers"` } -// SCORSHmasterState represents the runtime state of the master -type SCORSHmasterState struct { - Spooler chan SCORSHmsg - StatusChan chan SCORSHmsg - Repos map[string][]*SCORSHworker +// masterState represents the runtime state of the master +type masterState struct { + Spooler chan spoolMsg + StatusChan chan spoolMsg + Repos map[string][]*worker WorkingMsg map[string]int } -// SCORSHmaster represents the configuration and state of the master -type SCORSHmaster struct { - SCORSHmasterCfg `yaml:",inline"` - SCORSHmasterState +// master represents the configuration and state of the master +type master struct { + masterCfg `yaml:",inline"` + masterState } -// SCORSHtag is the type of commands sent by clients -type SCORSHtag struct { +// clientCmd is the type of commands sent by clients +type clientCmd struct { Tag string `yaml:"s_tag"` Args []string `yaml:"s_args"` } -// SCORSHclientMsg is the list of commands sent by a client -type SCORSHclientMsg struct { - Tags []SCORSHtag `yaml:"scorsh"` +// clientMsg is the list of commands sent by a client +type clientMsg struct { + Tags []clientCmd `yaml:"scorsh"` } //////////////////////// -func (cfg *SCORSHmaster) String() string { +func (cfg *master) String() string { var buff bytes.Buffer @@ -115,7 +115,7 @@ func (cfg *SCORSHmaster) String() string { return buff.String() } -func (msg *SCORSHmsg) String() string { +func (msg *spoolMsg) String() string { var buff bytes.Buffer fmt.Fprintf(&buff, "Id: %s\n", msg.ID) @@ -129,7 +129,7 @@ func (msg *SCORSHmsg) String() string { } -func (w *SCORSHworker) String() string { +func (w *worker) String() string { var buff bytes.Buffer fmt.Fprintf(&buff, "Name: %s\n", w.Name) @@ -142,7 +142,7 @@ func (w *SCORSHworker) String() string { return buff.String() } -func (msg *SCORSHclientMsg) String() string { +func (msg *clientMsg) String() string { var buff bytes.Buffer @@ -13,7 +13,7 @@ import ( // Matches returns true if the configured repo:branch of the worker // matches the repo and branch provided as arguments -func (w *SCORSHworker) Matches(repo, branch string) bool { +func (w *worker) Matches(repo, branch string) bool { for _, r := range w.Repos { parts := strings.SplitN(r, ":", 2) @@ -32,7 +32,7 @@ func (w *SCORSHworker) Matches(repo, branch string) bool { // LoadKeyrings loads the configured keyrings for all the commands // managed by the worker -func (w *SCORSHworker) LoadKeyrings() error { +func (w *worker) LoadKeyrings() error { w.Keys = make(map[string]openpgp.KeyRing) w.TagKeys = make(map[string]map[string]bool) @@ -72,7 +72,7 @@ func (w *SCORSHworker) LoadKeyrings() error { } // LoadTags loads all the configured commands for the worker -func (w *SCORSHworker) LoadTags() error { +func (w *worker) LoadTags() error { wTags, err := ioutil.ReadFile(w.Tagfile) if err != nil { @@ -90,9 +90,9 @@ func (w *SCORSHworker) LoadTags() error { } // -func runWorker(w *SCORSHworker) { +func runWorker(w *worker) { - var msg SCORSHmsg + var msg spoolMsg log.Printf("[worker: %s] Started\n", w.Name) @@ -116,8 +116,8 @@ func runWorker(w *SCORSHworker) { } // StartWorkers starts all the workers specified in a given -// configuration and fills in the SCORSHmaster struct -func startWorkers(master *SCORSHmaster) error { +// configuration and fills in the master struct +func startWorkers(master *master) error { numWorkers := len(master.Workers) @@ -130,7 +130,7 @@ func startWorkers(master *SCORSHmaster) error { worker := &(master.Workers[w]) // Set the Status and Msg channels worker.StatusChan = master.StatusChan - worker.MsgChan = make(chan SCORSHmsg, 10) + worker.MsgChan = make(chan spoolMsg, 10) // Load worker tags from worker.Tagfile err := worker.LoadTags() |