summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatolaZ <katolaz@freaknet.org>2017-07-11 14:38:55 +0100
committerKatolaZ <katolaz@freaknet.org>2017-07-11 14:38:55 +0100
commit32b09256150d139e77d04533f28d0c26a32b12bd (patch)
tree9d5aff595a1af5afee566b433d0466416d4f6691
parent3b752dc02e8ac2048c3dc6efa37145c679502c84 (diff)
added notes.txt on the architecture, and a sample worker_config
-rw-r--r--commits.go101
-rw-r--r--config.go2
-rw-r--r--notes.txt54
-rw-r--r--scorsh.go11
-rw-r--r--worker_config.cfg37
5 files changed, 198 insertions, 7 deletions
diff --git a/commits.go b/commits.go
new file mode 100644
index 0000000..c429bca
--- /dev/null
+++ b/commits.go
@@ -0,0 +1,101 @@
+package main
+
+import (
+ "fmt"
+ "github.com/KatolaZ/git2go"
+ "golang.org/x/crypto/openpgp"
+ "os"
+ "strings"
+ "log"
+)
+
+func CommitToString(commit *git.Commit) string {
+
+ var ret string
+
+ ret += fmt.Sprintf("type: %s\n", commit.Type())
+ ret += fmt.Sprintf("Id: %s\n", commit.Id())
+ ret += fmt.Sprintf("Author: %s\n", commit.Author())
+ ret += fmt.Sprintf("Message: %s\n", commit.Message())
+ ret += fmt.Sprintf("Parent-count: %d\n", commit.ParentCount())
+
+ return ret
+}
+
+// FIXME: RETURN THE ENTITY PROVIDED BY THE CHECK, OR nil
+func check_signature(commit *git.Commit, keyring *openpgp.KeyRing) (signature, signed string, err error) {
+
+ signature, signed, err = commit.ExtractSignature()
+ if err == nil {
+
+ _, err_sig :=
+ openpgp.CheckArmoredDetachedSignature(*keyring, strings.NewReader(signed),
+ strings.NewReader(signature))
+
+ if err_sig == nil {
+ fmt.Printf("Good signature \n")
+ return signature, signed, nil
+ }
+ err = err_sig
+ }
+
+ return "", "", err
+}
+
+
+// traverse all the commits between two references, looking for scorsh
+// commands
+// fixme: we don't have just one keyring here....
+func walk_commits(msg SCORSHmsg, keyring openpgp.KeyRing) int {
+
+ fmt.Printf("Inside parse_commits\n")
+
+ reponame := msg.repo
+ old_rev := msg.old_rev
+ new_rev := msg.new_rev
+
+ repo, err := git.OpenRepository(reponame)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error while opening repository %s (%s)\n",
+ reponame, err)
+ return SCORSH_ERR_NO_REPO
+ }
+
+ old_rev_oid, err := git.NewOid(old_rev)
+
+ oldrev_commit, err := repo.LookupCommit(old_rev_oid)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", old_rev)
+ return SCORSH_ERR_NO_COMMIT
+ }
+
+ new_rev_oid, err := git.NewOid(new_rev)
+
+ newrev_commit, err := repo.LookupCommit(new_rev_oid)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", new_rev)
+ return SCORSH_ERR_NO_COMMIT
+ }
+
+ cur_commit := newrev_commit
+
+ for cur_commit.Id().String() != oldrev_commit.Id().String() {
+
+ commit, err := repo.LookupCommit(cur_commit.Id())
+ if err == nil {
+
+ fmt.Printf("%s", CommitToString(commit))
+ //signature, signed, err := check_signature(commit, &keyring)
+ _, _, err := check_signature(commit, &keyring)
+ if err != nil {
+ log.Printf("%s\n", SCORSHErr(SCORSH_ERR_SIGNATURE))
+
+ }
+ cur_commit = commit.Parent(0)
+ } else {
+ fmt.Printf("Commit %x not found!\n", cur_commit.Id())
+ return SCORSH_ERR_NO_COMMIT
+ }
+ }
+ return 0
+}
diff --git a/config.go b/config.go
index 6d8786f..452f187 100644
--- a/config.go
+++ b/config.go
@@ -28,7 +28,7 @@ type SCORSHcfg struct {
// Read a configuration from fname or die
-func ReadConfig(fname string) *SCORSHcfg {
+func ReadGlobalConfig(fname string) *SCORSHcfg {
data, err := ioutil.ReadFile(fname)
if err != nil {
diff --git a/notes.txt b/notes.txt
new file mode 100644
index 0000000..618fcbf
--- /dev/null
+++ b/notes.txt
@@ -0,0 +1,54 @@
+## structure
+
+- we read the list of workers from the config file. Each worker
+ record consists of
+
+ - a list of repos/branches
+ - a folder where the configs and logs are kept
+ - a logfile
+ - a tagfile with the definition of tags
+ - a list of keyring files
+
+## master logic
+
+- in main() (master) we create a worker for each worker record,
+ maintaining a map of which worker can process commands for which
+ repo/branch
+
+- The spooler receives and processes CREATE events from the spool. It
+ parses each message and forwards it to the corresponding worker(s).
+
+- When the worker is done, it notifies the master, which will delete
+ the corresponding file from the spool.
+
+
+
+## worker logic
+
+- Each worker reads a configuration file containing the definition of
+ the tags it can manage.
+
+- Each tag is associated to a set of commands (URLs) and to a set of
+ keyrings.
+
+- A worker maintains a list of accepted scorsh tags, a map of
+ keyrings[tags], and a map of commands[tags].
+
+When a new scorsh message is received by a worker, it looks through
+the commit history for commits containing schorsh-tags. For each
+scorsh-tag found, the worker looks if the tag is among the supported
+ones, then checks if the commit can be verified by one of the keyrings
+associated to the tag. If the set of keyrings for that tag is empty,
+the tag is not allowed to run (this is a quick way to disable tags).
+
+(we might want to add an option to the definition of a scorsh-tag,
+which allows to run the commands from unsigned and/or unverified
+commits. This would be very dangerous though.)
+
+Then, if the tag is allowed to run, the worker executes each of the
+commands in the tag definition, replacing arguments as needed. If a
+command is a script (file://...), then it must also correspon to the
+hash specified in the config, otherwise it will not be executed.
+
+When the worker is finished with all the commands for all the commits,
+it will notify the master.
diff --git a/scorsh.go b/scorsh.go
index 08fc962..07745b3 100644
--- a/scorsh.go
+++ b/scorsh.go
@@ -14,11 +14,6 @@ const (
SCORSH_ERR_SIGNATURE
)
-type SCORSHconf struct {
- spool string
-}
-
-
type SCORSHmsg struct {
repo string
@@ -60,8 +55,12 @@ func main() {
flag.Parse()
- cfg := ReadConfig(*conf_file)
+ cfg := ReadGlobalConfig(*conf_file)
+ msg, status := StartWorkers(cfg)
+
+
+
log.Printf("%s\n", cfg)
}
diff --git a/worker_config.cfg b/worker_config.cfg
new file mode 100644
index 0000000..5173b6f
--- /dev/null
+++ b/worker_config.cfg
@@ -0,0 +1,37 @@
+#
+# This is the typical worker configuration file. The file should be
+# called "worker_config.cfg", and will be placed inside the worker
+# directory. It defines the tags understood by the worker, with the
+# corresponding list of commands
+#
+#
+
+
+---
+w_tags:
+ [
+ {
+ t_name: "BUILD",
+ t_keyrings: ["build_keyring.asc", "general_keyring.asc"],
+ t_commands: [
+ {
+ c_url: "file:///home/user/bin/script.sh $1 $2",
+ c_hash: "12da324fb76s924acbce"
+ },
+ {
+ c_url: "http://my.server.net/call.pl?branch=$1"
+ }
+ ]
+ },
+ {
+ t_name: "PUBLISH",
+ t_keyrings: ["web_developers.asc"],
+ t_commands: [
+ {
+ c_url: "file:///usr/local/bin/publish.py $repo $branch",
+ c_hash: "3234567898765432345678"
+ }
+ ]
+ }
+ ]
+... \ No newline at end of file