type renamed to avoid the SCORSH prefix

devel
KatolaZ 8 years ago
parent 587c8bf415
commit d3105e671a
  1. 106
      commits.go
  2. 4
      config.go
  3. 4
      exec.go
  4. 14
      scorshd.go
  5. 8
      spooler.go
  6. 88
      types.go
  7. 16
      workers.go

@ -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()

Loading…
Cancel
Save