From 0003d5d983c1386a697dab19b77d520354dbc840 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Mon, 22 Dec 2014 13:13:47 -0800 Subject: [PATCH 1/8] contrib: add git-sync container --- contrib/git-sync/Dockerfile | 4 +++ contrib/git-sync/README.md | 16 +++++++++ contrib/git-sync/main.go | 72 +++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 contrib/git-sync/Dockerfile create mode 100644 contrib/git-sync/README.md create mode 100644 contrib/git-sync/main.go diff --git a/contrib/git-sync/Dockerfile b/contrib/git-sync/Dockerfile new file mode 100644 index 00000000000..2c5596c7b90 --- /dev/null +++ b/contrib/git-sync/Dockerfile @@ -0,0 +1,4 @@ +FROM golang:1.4-onbuild +VOLUME ["/git"] +CMD ["-dest", "/git"] +ENTRYPOINT ["/go/bin/git-sync"] diff --git a/contrib/git-sync/README.md b/contrib/git-sync/README.md new file mode 100644 index 00000000000..a3059d91cd6 --- /dev/null +++ b/contrib/git-sync/README.md @@ -0,0 +1,16 @@ +# git-sync + +git-sync is a command that periodically sync a git repository to a local directory. + +It can be used to source a container volume with the content of a git repo. + +## Usage + +``` +# build the container +docker build -t git-sync . +# run the git-sync container +docker run -d -e INTERVAL=1s -e REPO=https://github.com/GoogleCloudPlatform/kubernetes -e BRANCH=gh-pages -v /git-data:/usr/share/nginx/html git-sync +# run a nginx container to serve sync'ed content +docker run -d -p 8080:80 -v /git-data:/var/www nginx +``` diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go new file mode 100644 index 00000000000..2d53e259dce --- /dev/null +++ b/contrib/git-sync/main.go @@ -0,0 +1,72 @@ +package main // import "github.com/GoogleCloudPlatform/kubernetes/git-sync" + +import ( + "flag" + "log" + "net/http" + "os" + "os/exec" + "path" + "strings" + "time" +) + +var interval = flag.String("interval", env("INTERVAL", "60s"), "git pull interval") +var repo = flag.String("repo", env("REPO", ""), "git repo url") +var branch = flag.String("branch", env("BRANCH", "master"), "git branch") +var hook = flag.String("hook", env("HOOK", "/"), "web hook path") +var dest = flag.String("dest", env("DEST", ""), "destination path") + +func env(key, def string) string { + if env := os.Getenv(key); env != "" { + return env + } + return def +} + +const usage = "usage: REPO= DEST= [INTERVAL= BRANCH= HOOK=] git-sync -repo GIT_REPO_URL -dest PATH [-interval -branch -hook]" + +func main() { + flag.Parse() + if *repo == "" || *dest == "" { + flag.Usage() + log.Fatal(usage) + } + pullInterval, err := time.ParseDuration(*interval) + if err != nil { + log.Fatalf("error parsing time duration %q: %v", *interval, err) + } + if _, err := exec.LookPath("git"); err != nil { + log.Fatalf("required git executable not found: %v", err) + } + go func() { + for _ = range time.Tick(pullInterval) { + gitSync() + } + }() + http.HandleFunc(*hook, func(w http.ResponseWriter, r *http.Request) { + gitSync() + }) + log.Fatal(http.ListenAndServe(":8080", nil)) +} + +func gitSync() { + if _, err := os.Stat(path.Join(*dest, ".git")); os.IsNotExist(err) { + cmd := exec.Command("git", "clone", "-b", *branch, *repo, *dest) + output, err := cmd.CombinedOutput() + if err != nil { + log.Printf("command %q : %v", strings.Join(cmd.Args, " "), err) + return + } + log.Println(string(output)) + return + } + cmd := exec.Command("git", "pull", "origin", *branch) + cmd.Dir = *dest + output, err := cmd.CombinedOutput() + if err != nil { + log.Printf("command %q : %v", strings.Join(cmd.Args, " "), err) + return + } + log.Println(string(output)) +} From d67db4ecfa6f5648909fdddf719af42368208480 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Mon, 22 Dec 2014 17:34:56 -0800 Subject: [PATCH 2/8] config/git-sync: add envvar prefix, fix README --- contrib/git-sync/Dockerfile | 2 +- contrib/git-sync/README.md | 4 ++-- contrib/git-sync/main.go | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/git-sync/Dockerfile b/contrib/git-sync/Dockerfile index 2c5596c7b90..6929d15b454 100644 --- a/contrib/git-sync/Dockerfile +++ b/contrib/git-sync/Dockerfile @@ -1,4 +1,4 @@ FROM golang:1.4-onbuild VOLUME ["/git"] -CMD ["-dest", "/git"] +ENV GIT_SYNC_DEST /git ENTRYPOINT ["/go/bin/git-sync"] diff --git a/contrib/git-sync/README.md b/contrib/git-sync/README.md index a3059d91cd6..1ec2d997066 100644 --- a/contrib/git-sync/README.md +++ b/contrib/git-sync/README.md @@ -10,7 +10,7 @@ It can be used to source a container volume with the content of a git repo. # build the container docker build -t git-sync . # run the git-sync container -docker run -d -e INTERVAL=1s -e REPO=https://github.com/GoogleCloudPlatform/kubernetes -e BRANCH=gh-pages -v /git-data:/usr/share/nginx/html git-sync +docker run -d -e GIT_SYNC_INTERVAL=1s -e GIT_SYNC_REPO=https://github.com/GoogleCloudPlatform/kubernetes -e GIT_SYNC_BRANCH=gh-pages -v /git-data:/git git-sync # run a nginx container to serve sync'ed content -docker run -d -p 8080:80 -v /git-data:/var/www nginx +docker run -d -p 8080:80 -v /git-data:/usr/share/nginx/html nginx ``` diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go index 2d53e259dce..4b7cbf2f1be 100644 --- a/contrib/git-sync/main.go +++ b/contrib/git-sync/main.go @@ -11,11 +11,11 @@ import ( "time" ) -var interval = flag.String("interval", env("INTERVAL", "60s"), "git pull interval") -var repo = flag.String("repo", env("REPO", ""), "git repo url") -var branch = flag.String("branch", env("BRANCH", "master"), "git branch") -var hook = flag.String("hook", env("HOOK", "/"), "web hook path") -var dest = flag.String("dest", env("DEST", ""), "destination path") +var interval = flag.String("interval", env("GIT_SYNC_INTERVAL", "60s"), "git pull interval") +var repo = flag.String("repo", env("GIT_SYNC_REPO", ""), "git repo url") +var branch = flag.String("branch", env("GIT_SYNC_BRANCH", "master"), "git branch") +var handler = flag.String("handler", env("GIT_SYNC_HANDLER", "/"), "web hook handler") +var dest = flag.String("dest", env("GIT_SYNC_DEST", ""), "destination path") func env(key, def string) string { if env := os.Getenv(key); env != "" { @@ -24,7 +24,7 @@ func env(key, def string) string { return def } -const usage = "usage: REPO= DEST= [INTERVAL= BRANCH= HOOK=] git-sync -repo GIT_REPO_URL -dest PATH [-interval -branch -hook]" +const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_INTERVAL= GIT_SYNC_BRANCH= GIT_SYNC_HANDLER=] git-sync -repo GIT_REPO_URL -dest PATH [-interval -branch -handler]" func main() { flag.Parse() @@ -44,7 +44,7 @@ func main() { gitSync() } }() - http.HandleFunc(*hook, func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc(*handler, func(w http.ResponseWriter, r *http.Request) { gitSync() }) log.Fatal(http.ListenAndServe(":8080", nil)) From 9f37c9d4112a0311f725137b6cd0fba5db4c394d Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Tue, 23 Dec 2014 13:54:29 -0800 Subject: [PATCH 3/8] contrib/git-sync: add atomic checkout --- contrib/git-sync/README.md | 2 +- contrib/git-sync/main.go | 107 +++++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 18 deletions(-) diff --git a/contrib/git-sync/README.md b/contrib/git-sync/README.md index 1ec2d997066..52bf2c655d9 100644 --- a/contrib/git-sync/README.md +++ b/contrib/git-sync/README.md @@ -12,5 +12,5 @@ docker build -t git-sync . # run the git-sync container docker run -d -e GIT_SYNC_INTERVAL=1s -e GIT_SYNC_REPO=https://github.com/GoogleCloudPlatform/kubernetes -e GIT_SYNC_BRANCH=gh-pages -v /git-data:/git git-sync # run a nginx container to serve sync'ed content -docker run -d -p 8080:80 -v /git-data:/usr/share/nginx/html nginx +docker run -d -p 8080:80 -v /git-data/HEAD:/usr/share/nginx/html nginx ``` diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go index 4b7cbf2f1be..3060fb71e03 100644 --- a/contrib/git-sync/main.go +++ b/contrib/git-sync/main.go @@ -2,6 +2,7 @@ package main // import "github.com/GoogleCloudPlatform/kubernetes/git-sync" import ( "flag" + "fmt" "log" "net/http" "os" @@ -39,34 +40,106 @@ func main() { if _, err := exec.LookPath("git"); err != nil { log.Fatalf("required git executable not found: %v", err) } + repo, err := NewRepo() + if err != nil { + log.Fatalf("error creating repo: %v", err) + } + syncc := make(chan struct{}) + tick := time.Tick(pullInterval) go func() { - for _ = range time.Tick(pullInterval) { - gitSync() + for { + repo.Sync() + select { + case <-tick: + case <-syncc: + } } }() http.HandleFunc(*handler, func(w http.ResponseWriter, r *http.Request) { - gitSync() + syncc <- struct{}{} }) log.Fatal(http.ListenAndServe(":8080", nil)) } -func gitSync() { - if _, err := os.Stat(path.Join(*dest, ".git")); os.IsNotExist(err) { - cmd := exec.Command("git", "clone", "-b", *branch, *repo, *dest) - output, err := cmd.CombinedOutput() - if err != nil { - log.Printf("command %q : %v", strings.Join(cmd.Args, " "), err) - return - } - log.Println(string(output)) - return +type Repo struct { + basePath string + mirrorPath string + lastRev string +} + +func NewRepo() (*Repo, error) { + mirrorRepoPath := path.Join(*dest, ".git") + _, err := os.Stat(mirrorRepoPath) + if err == nil { + log.Printf("found existing mirror repo %q", mirrorRepoPath) + return &Repo{ + basePath: *dest, + mirrorPath: mirrorRepoPath, + }, nil } - cmd := exec.Command("git", "pull", "origin", *branch) - cmd.Dir = *dest + if !os.IsNotExist(err) { + return nil, fmt.Errorf("error checking repo %q: %v", mirrorRepoPath, err) + } + cmd := exec.Command("git", "clone", "--mirror", "-b", *branch, *repo, mirrorRepoPath) output, err := cmd.CombinedOutput() if err != nil { - log.Printf("command %q : %v", strings.Join(cmd.Args, " "), err) + return nil, fmt.Errorf("error cloning repo %q: %v:", strings.Join(cmd.Args, " "), err) + } + log.Printf("clone %q: %s", *repo, string(output)) + return &Repo{ + basePath: *dest, + mirrorPath: mirrorRepoPath, + }, nil +} + +func (r *Repo) Sync() { + cmd := exec.Command("git", "fetch", "origin", *branch) + cmd.Dir = r.mirrorPath + output, err := cmd.CombinedOutput() + if err != nil { + log.Printf("error running command %q: %v", strings.Join(cmd.Args, " "), err) + return + } + log.Printf("fetch: %s", string(output)) + cmd = exec.Command("git", "rev-parse", "HEAD") + cmd.Dir = r.mirrorPath + output, err = cmd.CombinedOutput() + if err != nil { + log.Printf("error running command %q: %v", strings.Join(cmd.Args, " "), err) + return + } + rev := strings.TrimSpace(string(output)) + if rev == r.lastRev { + log.Printf("no new rev since last check %q", rev) + return + } + r.lastRev = rev + log.Printf("HEAD is: %q", rev) + repoPath := path.Join(r.basePath, rev) + _, err = os.Stat(repoPath) + if err == nil { + log.Printf("found existing repo: %q", repoPath) + return + } + if !os.IsNotExist(err) { + log.Printf("error stating repo %q: %v", repoPath, err) + return + } + cmd = exec.Command("git", "clone", r.mirrorPath, repoPath) + output, err = cmd.CombinedOutput() + if err != nil { + log.Printf("error running command %q : %v", strings.Join(cmd.Args, " "), err) + return + } + log.Printf("clone %q: %v", repoPath, string(output)) + tempPath := path.Join(r.basePath, "HEAD."+rev) + if err := os.Symlink(rev, tempPath); err != nil { + log.Printf("error creating temporary symlink %q: %v", tempPath, err) + return + } + linkPath := path.Join(r.basePath, "HEAD") + if err := os.Rename(tempPath, linkPath); err != nil { + log.Printf("error moving symlink %q: %v", linkPath, err) return } - log.Println(string(output)) } From 79dd775d72110df443630a2ae1a79b5d350382de Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Tue, 23 Dec 2014 15:21:51 -0800 Subject: [PATCH 4/8] contrib/git-sync: add comment --- contrib/git-sync/main.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go index 3060fb71e03..b0aff6179b5 100644 --- a/contrib/git-sync/main.go +++ b/contrib/git-sync/main.go @@ -1,3 +1,21 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// git-sync is a command that periodically sync a git repository to a local directory. + package main // import "github.com/GoogleCloudPlatform/kubernetes/git-sync" import ( @@ -67,6 +85,7 @@ type Repo struct { lastRev string } +// NewRepo initalize a local bare repository mirror. func NewRepo() (*Repo, error) { mirrorRepoPath := path.Join(*dest, ".git") _, err := os.Stat(mirrorRepoPath) @@ -92,6 +111,9 @@ func NewRepo() (*Repo, error) { }, nil } +// Sync fetch new revision from the origin remote in the bare repository +// create a new checkout named after the revision +// update HEAD symlink to point to the new revision func (r *Repo) Sync() { cmd := exec.Command("git", "fetch", "origin", *branch) cmd.Dir = r.mirrorPath From 0415b63ab49310a23b9296e65447fbb297cbb099 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Thu, 29 Jan 2015 15:39:51 -0800 Subject: [PATCH 5/8] contrib/git-sync: remove sync loop, simplify logic --- contrib/git-sync/README.md | 6 +- contrib/git-sync/main.go | 149 ++++++++++--------------------------- 2 files changed, 41 insertions(+), 114 deletions(-) diff --git a/contrib/git-sync/README.md b/contrib/git-sync/README.md index 52bf2c655d9..f8faa4a0cd1 100644 --- a/contrib/git-sync/README.md +++ b/contrib/git-sync/README.md @@ -1,6 +1,6 @@ # git-sync -git-sync is a command that periodically sync a git repository to a local directory. +git-sync is a command that pull a git repository to a local directory. It can be used to source a container volume with the content of a git repo. @@ -10,7 +10,7 @@ It can be used to source a container volume with the content of a git repo. # build the container docker build -t git-sync . # run the git-sync container -docker run -d -e GIT_SYNC_INTERVAL=1s -e GIT_SYNC_REPO=https://github.com/GoogleCloudPlatform/kubernetes -e GIT_SYNC_BRANCH=gh-pages -v /git-data:/git git-sync +docker run -d GIT_SYNC_REPO=https://github.com/GoogleCloudPlatform/kubernetes -e GIT_SYNC_BRANCH=gh-pages -r HEAD -v /git-data:/git git-sync # run a nginx container to serve sync'ed content -docker run -d -p 8080:80 -v /git-data/HEAD:/usr/share/nginx/html nginx +docker run -d -p 8080:80 -v /git-data:/usr/share/nginx/html nginx ``` diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go index b0aff6179b5..355c0e1bc7e 100644 --- a/contrib/git-sync/main.go +++ b/contrib/git-sync/main.go @@ -14,27 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. */ -// git-sync is a command that periodically sync a git repository to a local directory. +// git-sync is a command that pull a git repository to a local directory. -package main // import "github.com/GoogleCloudPlatform/kubernetes/git-sync" +package main // import "github.com/GoogleCloudPlatform/kubernetes/contrib/git-sync" import ( "flag" "fmt" "log" - "net/http" "os" "os/exec" "path" "strings" - "time" ) -var interval = flag.String("interval", env("GIT_SYNC_INTERVAL", "60s"), "git pull interval") -var repo = flag.String("repo", env("GIT_SYNC_REPO", ""), "git repo url") -var branch = flag.String("branch", env("GIT_SYNC_BRANCH", "master"), "git branch") -var handler = flag.String("handler", env("GIT_SYNC_HANDLER", "/"), "web hook handler") -var dest = flag.String("dest", env("GIT_SYNC_DEST", ""), "destination path") +var flRepo = flag.String("repo", env("GIT_SYNC_REPO", ""), "git repo url") +var flBranch = flag.String("branch", env("GIT_SYNC_BRANCH", "master"), "git branch") +var flRev = flag.String("rev", env("GIT_SYNC_BRANCH", "HEAD"), "git rev") +var flDest = flag.String("dest", env("GIT_SYNC_DEST", ""), "destination path") func env(key, def string) string { if env := os.Getenv(key); env != "" { @@ -43,125 +40,55 @@ func env(key, def string) string { return def } -const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_INTERVAL= GIT_SYNC_BRANCH= GIT_SYNC_HANDLER=] git-sync -repo GIT_REPO_URL -dest PATH [-interval -branch -handler]" +const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH=] git-sync -repo GIT_REPO_URL -dest PATH [-branch]" func main() { flag.Parse() - if *repo == "" || *dest == "" { + if *flRepo == "" || *flDest == "" { flag.Usage() log.Fatal(usage) } - pullInterval, err := time.ParseDuration(*interval) - if err != nil { - log.Fatalf("error parsing time duration %q: %v", *interval, err) - } if _, err := exec.LookPath("git"); err != nil { log.Fatalf("required git executable not found: %v", err) } - repo, err := NewRepo() - if err != nil { - log.Fatalf("error creating repo: %v", err) + if err := syncRepo(*flRepo, *flDest, *flBranch, *flRev); err != nil { + log.Fatalf("error syncing repo: %v", err) } - syncc := make(chan struct{}) - tick := time.Tick(pullInterval) - go func() { - for { - repo.Sync() - select { - case <-tick: - case <-syncc: - } +} + +// syncRepo syncs the branch of a given repository to the destination at the given rev. +func syncRepo(repo, dest, branch, rev string) error { + gitRepoPath := path.Join(dest, ".git") + _, err := os.Stat(gitRepoPath) + switch { + case os.IsNotExist(err): + // clone repo + cmd := exec.Command("git", "clone", "--no-checkout", "-b", branch, repo, dest) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("error cloning repo %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output)) } - }() - http.HandleFunc(*handler, func(w http.ResponseWriter, r *http.Request) { - syncc <- struct{}{} - }) - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -type Repo struct { - basePath string - mirrorPath string - lastRev string -} - -// NewRepo initalize a local bare repository mirror. -func NewRepo() (*Repo, error) { - mirrorRepoPath := path.Join(*dest, ".git") - _, err := os.Stat(mirrorRepoPath) - if err == nil { - log.Printf("found existing mirror repo %q", mirrorRepoPath) - return &Repo{ - basePath: *dest, - mirrorPath: mirrorRepoPath, - }, nil + log.Printf("clone %q: %s", repo, string(output)) + case err != nil: + return fmt.Errorf("error checking if repo exist %q: %v", gitRepoPath, err) } - if !os.IsNotExist(err) { - return nil, fmt.Errorf("error checking repo %q: %v", mirrorRepoPath, err) - } - cmd := exec.Command("git", "clone", "--mirror", "-b", *branch, *repo, mirrorRepoPath) + + // fetch branch + cmd := exec.Command("git", "fetch", "origin", branch) + cmd.Dir = dest output, err := cmd.CombinedOutput() if err != nil { - return nil, fmt.Errorf("error cloning repo %q: %v:", strings.Join(cmd.Args, " "), err) + return fmt.Errorf("error running command %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output)) } - log.Printf("clone %q: %s", *repo, string(output)) - return &Repo{ - basePath: *dest, - mirrorPath: mirrorRepoPath, - }, nil -} + log.Printf("fetch %q: %s", branch, string(output)) -// Sync fetch new revision from the origin remote in the bare repository -// create a new checkout named after the revision -// update HEAD symlink to point to the new revision -func (r *Repo) Sync() { - cmd := exec.Command("git", "fetch", "origin", *branch) - cmd.Dir = r.mirrorPath - output, err := cmd.CombinedOutput() - if err != nil { - log.Printf("error running command %q: %v", strings.Join(cmd.Args, " "), err) - return - } - log.Printf("fetch: %s", string(output)) - cmd = exec.Command("git", "rev-parse", "HEAD") - cmd.Dir = r.mirrorPath + // reset working copy + cmd = exec.Command("git", "reset", "--hard", rev) + cmd.Dir = dest output, err = cmd.CombinedOutput() if err != nil { - log.Printf("error running command %q: %v", strings.Join(cmd.Args, " "), err) - return - } - rev := strings.TrimSpace(string(output)) - if rev == r.lastRev { - log.Printf("no new rev since last check %q", rev) - return - } - r.lastRev = rev - log.Printf("HEAD is: %q", rev) - repoPath := path.Join(r.basePath, rev) - _, err = os.Stat(repoPath) - if err == nil { - log.Printf("found existing repo: %q", repoPath) - return - } - if !os.IsNotExist(err) { - log.Printf("error stating repo %q: %v", repoPath, err) - return - } - cmd = exec.Command("git", "clone", r.mirrorPath, repoPath) - output, err = cmd.CombinedOutput() - if err != nil { - log.Printf("error running command %q : %v", strings.Join(cmd.Args, " "), err) - return - } - log.Printf("clone %q: %v", repoPath, string(output)) - tempPath := path.Join(r.basePath, "HEAD."+rev) - if err := os.Symlink(rev, tempPath); err != nil { - log.Printf("error creating temporary symlink %q: %v", tempPath, err) - return - } - linkPath := path.Join(r.basePath, "HEAD") - if err := os.Rename(tempPath, linkPath); err != nil { - log.Printf("error moving symlink %q: %v", linkPath, err) - return + return fmt.Errorf("error running command %q : %v: %s", strings.Join(cmd.Args, " "), err, string(output)) } + log.Printf("reset %q: %v", rev, string(output)) + return nil } From 5aba5f00c0cf7dbd1b54083d559a49e47f959c53 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Thu, 29 Jan 2015 23:21:49 -0800 Subject: [PATCH 6/8] contrib/git-sync: add wait --- contrib/git-sync/main.go | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go index 355c0e1bc7e..7667e8df7a5 100644 --- a/contrib/git-sync/main.go +++ b/contrib/git-sync/main.go @@ -25,22 +25,37 @@ import ( "os" "os/exec" "path" + "strconv" "strings" + "time" ) -var flRepo = flag.String("repo", env("GIT_SYNC_REPO", ""), "git repo url") -var flBranch = flag.String("branch", env("GIT_SYNC_BRANCH", "master"), "git branch") -var flRev = flag.String("rev", env("GIT_SYNC_BRANCH", "HEAD"), "git rev") -var flDest = flag.String("dest", env("GIT_SYNC_DEST", ""), "destination path") +var flRepo = flag.String("repo", envString("GIT_SYNC_REPO", ""), "git repo url") +var flBranch = flag.String("branch", envString("GIT_SYNC_BRANCH", "master"), "git branch") +var flRev = flag.String("rev", envString("GIT_SYNC_BRANCH", "HEAD"), "git rev") +var flDest = flag.String("dest", envString("GIT_SYNC_DEST", ""), "destination path") +var flWait = flag.Int("wait", envInt("GIT_SYNC_WAIT", 0), "number of seconds to wait before exit") -func env(key, def string) string { +func envString(key, def string) string { if env := os.Getenv(key); env != "" { return env } return def } -const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH=] git-sync -repo GIT_REPO_URL -dest PATH [-branch]" +func envInt(key string, def int) int { + if env := os.Getenv(key); env != "" { + val, err := strconv.Atoi(env) + if err != nil { + log.Println("invalid value for %q: using default: %q", key, def) + return def + } + return val + } + return def +} + +const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH= GIT_SYNC_WAIT=] git-sync -repo GIT_REPO_URL -dest PATH [-branch -wait]" func main() { flag.Parse() @@ -54,6 +69,9 @@ func main() { if err := syncRepo(*flRepo, *flDest, *flBranch, *flRev); err != nil { log.Fatalf("error syncing repo: %v", err) } + log.Printf("wait %d seconds", *flWait) + time.Sleep(time.Duration(*flWait) * time.Second) + log.Println("done") } // syncRepo syncs the branch of a given repository to the destination at the given rev. From 19751abe138b7a92927ab56d39ecd55ea9a77ea7 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Mon, 2 Feb 2015 18:02:18 -0800 Subject: [PATCH 7/8] contrib/git-sync: add demo --- contrib/git-sync/demo/README.md | 28 +++++++++++ contrib/git-sync/demo/blog/archetypes/.keep | 0 contrib/git-sync/demo/blog/config.toml | 3 ++ contrib/git-sync/demo/blog/content/about.md | 9 ++++ .../git-sync/demo/blog/content/post/first.md | 9 ++++ contrib/git-sync/demo/blog/layouts/.keep | 0 contrib/git-sync/demo/blog/static/.keep | 0 contrib/git-sync/demo/config/pod.yaml | 50 +++++++++++++++++++ contrib/git-sync/demo/config/service.yaml | 8 +++ contrib/git-sync/demo/hugo/Dockerfile | 13 +++++ contrib/git-sync/demo/hugo/run-hugo | 6 +++ 11 files changed, 126 insertions(+) create mode 100644 contrib/git-sync/demo/README.md create mode 100644 contrib/git-sync/demo/blog/archetypes/.keep create mode 100644 contrib/git-sync/demo/blog/config.toml create mode 100644 contrib/git-sync/demo/blog/content/about.md create mode 100644 contrib/git-sync/demo/blog/content/post/first.md create mode 100644 contrib/git-sync/demo/blog/layouts/.keep create mode 100644 contrib/git-sync/demo/blog/static/.keep create mode 100644 contrib/git-sync/demo/config/pod.yaml create mode 100644 contrib/git-sync/demo/config/service.yaml create mode 100644 contrib/git-sync/demo/hugo/Dockerfile create mode 100755 contrib/git-sync/demo/hugo/run-hugo diff --git a/contrib/git-sync/demo/README.md b/contrib/git-sync/demo/README.md new file mode 100644 index 00000000000..b458135bfd9 --- /dev/null +++ b/contrib/git-sync/demo/README.md @@ -0,0 +1,28 @@ +# git-blog-demo + +This demo shows how to use the `git-sync` sidekick container along side `volumes` and `volumeMounts` to create a markdown powered blog. + +## How it works + +The pod is composed of 3 containers that share directories using 2 volumes: + +- The `git-sync` container clones a git repo into the `markdown` volume +- The `hugo` container read from the `markdown` volume and render it into the `html` volume. +- The `nginx` container serve the content from the `html` volume. + +## Usage + +Build the demo containers, and push them to a registry +`` +docker build -t /git-sync .. +docker build -t /hugo hugo/ +docker push /hugo /git-sync +``` + +Create the pod and the service for the blog +``` +kubectl pods create config/pod.html +kubectl services create config/pod.html +``` + +Open the external ip in your browser diff --git a/contrib/git-sync/demo/blog/archetypes/.keep b/contrib/git-sync/demo/blog/archetypes/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/git-sync/demo/blog/config.toml b/contrib/git-sync/demo/blog/config.toml new file mode 100644 index 00000000000..ab3aa9e446e --- /dev/null +++ b/contrib/git-sync/demo/blog/config.toml @@ -0,0 +1,3 @@ +baseurl = "http://example.com" +languageCode = "en-us" +title = "example blog" diff --git a/contrib/git-sync/demo/blog/content/about.md b/contrib/git-sync/demo/blog/content/about.md new file mode 100644 index 00000000000..afb2ac0f4bb --- /dev/null +++ b/contrib/git-sync/demo/blog/content/about.md @@ -0,0 +1,9 @@ ++++ +date = "2014-12-19T15:29:48-08:00" +draft = true +title = "about" ++++ + +## A headline + +Some content about the blog. diff --git a/contrib/git-sync/demo/blog/content/post/first.md b/contrib/git-sync/demo/blog/content/post/first.md new file mode 100644 index 00000000000..630bbbd01d3 --- /dev/null +++ b/contrib/git-sync/demo/blog/content/post/first.md @@ -0,0 +1,9 @@ ++++ +date = "2014-12-19T15:30:18-08:00" +draft = true +title = "first" ++++ + +## first port + +This is the first post. diff --git a/contrib/git-sync/demo/blog/layouts/.keep b/contrib/git-sync/demo/blog/layouts/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/git-sync/demo/blog/static/.keep b/contrib/git-sync/demo/blog/static/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/git-sync/demo/config/pod.yaml b/contrib/git-sync/demo/config/pod.yaml new file mode 100644 index 00000000000..75ff074c18b --- /dev/null +++ b/contrib/git-sync/demo/config/pod.yaml @@ -0,0 +1,50 @@ +id: blog-pod +kind: Pod +apiVersion: v1beta1 +desiredState: + manifest: + version: v1beta1 + containers: + - name: git-sync + image: proppy/git-sync + imagePullPolicy: PullAlways + env:: + - name: GIT_SYNC_REPO + value: https://github.com/proppy/blog.git + - name: GIT_SYNC_DEST + value: /git + volumeMounts: + - name: markdown + mountPath: /git + - name: hugo + image: proppy/hugo + imagePullPolicy: PullAlways + env: + - name: SRC + value: /src + - name: BUILD_DRAFT + value: 'true' + - name: BASE_URL + value: kube.proppy.sh + volumeMounts: + - name: markdown + mountPath: /src + - name: html + mountPath: /dest + - name: nginx + image: nginx + volumeMounts: + - name: html + mountPath: /usr/share/nginx/html + ports: + - name: http-server + containerPort: 80 + volumes: + - name: markdown + source: + emptyDir: {} + - name: html + source: + emptyDir: {} +labels: + name: blog diff --git a/contrib/git-sync/demo/config/service.yaml b/contrib/git-sync/demo/config/service.yaml new file mode 100644 index 00000000000..646b4c59aa6 --- /dev/null +++ b/contrib/git-sync/demo/config/service.yaml @@ -0,0 +1,8 @@ +id: blog-service +kind: Service +apiVersion: v1beta1 +port: 80 +containerPort: http-server +selector: + name: blog +createExternalLoadBalancer: true diff --git a/contrib/git-sync/demo/hugo/Dockerfile b/contrib/git-sync/demo/hugo/Dockerfile new file mode 100644 index 00000000000..40af5e67ed8 --- /dev/null +++ b/contrib/git-sync/demo/hugo/Dockerfile @@ -0,0 +1,13 @@ +FROM golang +RUN go get -v github.com/spf13/hugo +RUN git clone --recursive https://github.com/spf13/hugoThemes.git /themes +VOLUME ["/src", "/dest"] +EXPOSE 1313 +ENV SRC /src +ENV DEST /dest +ENV THEME hyde +ENV BUILD_DRAFT false +ENV BASE_URL "" +ADD run-hugo /run-hugo +ENTRYPOINT ["/run-hugo"] +CMD ["server", "--source=${SRC}", "--theme=${THEME}", "--buildDrafts=${BUILD_DRAFT}", "--baseUrl=${BASE_URL}", "--watch", "--destination=${DEST}", "--appendPort=false"] diff --git a/contrib/git-sync/demo/hugo/run-hugo b/contrib/git-sync/demo/hugo/run-hugo new file mode 100755 index 00000000000..c90daa85e25 --- /dev/null +++ b/contrib/git-sync/demo/hugo/run-hugo @@ -0,0 +1,6 @@ +#!/bin/bash +set -ex +if [ ! -d ${SRC}/themes ]; then + ln -s /themes ${SRC}/themes +fi +hugo $(eval echo $*) # force default CMD env expansion From 88734263141b50309f1ec0c4a6122a5c544a299a Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Mon, 2 Feb 2015 18:05:26 -0800 Subject: [PATCH 8/8] contrib/git-sync/demo: fix README, add license header --- contrib/git-sync/demo/README.md | 6 ++++-- contrib/git-sync/demo/hugo/run-hugo | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/contrib/git-sync/demo/README.md b/contrib/git-sync/demo/README.md index b458135bfd9..e2a72465b56 100644 --- a/contrib/git-sync/demo/README.md +++ b/contrib/git-sync/demo/README.md @@ -13,16 +13,18 @@ The pod is composed of 3 containers that share directories using 2 volumes: ## Usage Build the demo containers, and push them to a registry -`` + +``` docker build -t /git-sync .. docker build -t /hugo hugo/ docker push /hugo /git-sync ``` Create the pod and the service for the blog + ``` kubectl pods create config/pod.html kubectl services create config/pod.html ``` -Open the external ip in your browser +Open the service external ip in your browser diff --git a/contrib/git-sync/demo/hugo/run-hugo b/contrib/git-sync/demo/hugo/run-hugo index c90daa85e25..37636025523 100755 --- a/contrib/git-sync/demo/hugo/run-hugo +++ b/contrib/git-sync/demo/hugo/run-hugo @@ -1,4 +1,19 @@ #!/bin/bash + +# Copyright 2014 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + set -ex if [ ! -d ${SRC}/themes ]; then ln -s /themes ${SRC}/themes