From 6514fef599872aa508895af7a2c27473adedc968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Meireles?= Date: Thu, 7 Jan 2016 20:47:38 +0000 Subject: [PATCH 1/3] bundle build date into running blob MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: António Meireles --- Makefile | 4 +++- main.go | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 87c8816..5bf7d2e 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ export GOOS=darwin export CGO_ENABLED=1 VERSION := $(shell git describe --abbrev=6 --dirty=-unreleased --always --tags) +BUILDDATE = $(shell /bin/date "+%FT%T%Z") ifeq ($(DEBUG),true) GO_GCFLAGS := -gcflags "-N -l" @@ -10,7 +11,8 @@ else GO_LDFLAGS := $(GO_LDFLAGS) -w -s endif -GO_LDFLAGS := $(GO_LDFLAGS) -X main.Version=$(VERSION) +GO_LDFLAGS := $(GO_LDFLAGS) -X main.Version=$(VERSION) \ + -X main.BuildDate=$(BUILDDATE) all: corectl docs @git status diff --git a/main.go b/main.go index 6fc3647..2889d54 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ import ( "log" "os" "strings" + "time" "github.com/google/go-github/github" "github.com/spf13/cobra" @@ -45,7 +46,7 @@ var ( engine sessionContext // -ldflags "-X main.Version= // `git describe --abbrev=6 --dirty=-unreleased --always --tags`" - Version string + Version, BuildDate string ) func main() { @@ -72,13 +73,15 @@ func init() { func versionCommand(cmd *cobra.Command, args []string) { var ( - err error - latest *github.RepositoryRelease + err error + latest *github.RepositoryRelease + stamp, _ = time.Parse("2006-01-02T15:04:05MST", BuildDate) ) fmt.Printf("%s\n%s\n\n", "CoreOS over OSX made simple.", "❯❯❯ http://github.com/TheNewNormal/corectl") + fmt.Printf("Installed version: %s (built at %v)\n", + strings.TrimPrefix(Version, "v"), stamp) - fmt.Println("Installed version:", strings.TrimPrefix(Version, "v")) if latest, _, err = github.NewClient(nil).Repositories.GetLatestRelease("TheNewNormal", "corectl"); err != nil { From 0eb0dc4b1c080fe72ecff3fa478e77df99489461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Meireles?= Date: Fri, 8 Jan 2016 15:37:00 +0000 Subject: [PATCH 2/3] force recreation of local OEMfied images if they deemed too old MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - this will allow us for transparent migrations any time we find the need to add or modify hooks in the images we generate Signed-off-by: António Meireles --- globals.go | 2 ++ list.go | 25 ++++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/globals.go b/globals.go index 432e227..d5d7405 100644 --- a/globals.go +++ b/globals.go @@ -22,6 +22,8 @@ import ( "github.com/spf13/viper" ) +const LatestImageBreackage = "2016-01-08T16:00:00WET" + type ( vmContext struct{ vm *VMInfo } sessionContext struct { diff --git a/list.go b/list.go index 6f70f50..51871d1 100644 --- a/list.go +++ b/list.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" "path/filepath" + "time" "github.com/blang/semver" "github.com/spf13/cobra" @@ -87,9 +88,10 @@ func init() { func localImages() (local map[string]semver.Versions, err error) { var ( - files []os.FileInfo - f os.FileInfo - channel string + files []os.FileInfo + f os.FileInfo + channel string + stamp, _ = time.Parse("2006-01-02T15:04:05MST", LatestImageBreackage) ) local = make(map[string]semver.Versions, 0) for _, channel = range DefaultChannels { @@ -100,11 +102,20 @@ func localImages() (local map[string]semver.Versions, err error) { var v semver.Versions for _, f = range files { if f.IsDir() { - var s semver.Version - if s, err = semver.Make(f.Name()); err != nil { - return + if f.ModTime().After(stamp) { + var s semver.Version + if s, err = semver.Make(f.Name()); err != nil { + return + } + v = append(v, s) + } else { + // force rebuild if local image assembled before last time + // we changed its expcted format + if err = os.RemoveAll(filepath.Join(engine.imageDir, + channel, f.Name())); err != nil { + return + } } - v = append(v, s) } } semver.Sort(v) From e7e2441a24bfe93ea2e44152be90af98da3ad578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Meireles?= Date: Fri, 8 Jan 2016 15:40:33 +0000 Subject: [PATCH 3/3] add multi-user support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - it's now possible for different users, concurrently, and independent of each other, to run `corectl` on a OS X box. - the CoreOS images already on-disk will be regenerated, but overall the update process from older versions should be transparent. Signed-off-by: António Meireles --- README.md | 2 +- globals.go | 16 ++++++++++------ helpers.go | 8 +++++++- run.go | 55 +++++++++++++++++++++++++----------------------------- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 6bc61e9..bbea195 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Update Strategy: No Reboots Last login: Tue Aug 25 13:23:20 +0000 2015 on /dev/tty1. core@localhost ~ $ ``` -you 'll find out that `/Users` is available (via NFS) already inside your VM. +you 'll find out that your `${HOME}` become available (via NFS) inside your VM. that will come handy when you come to play with `docker` volumes later... ### usage diff --git a/globals.go b/globals.go index d5d7405..1f8ea49 100644 --- a/globals.go +++ b/globals.go @@ -27,10 +27,10 @@ const LatestImageBreackage = "2016-01-08T16:00:00WET" type ( vmContext struct{ vm *VMInfo } sessionContext struct { - configDir, imageDir, runDir, pwd, uid, gid, username string - hasPowers, debug, json bool - rawArgs *viper.Viper - VMs []vmContext + configDir, imageDir, runDir, pwd, uid, gid, homedir string + hasPowers, debug, json bool + rawArgs *viper.Viper + VMs []vmContext } // VMInfo - per VM settings VMInfo struct { @@ -274,16 +274,20 @@ COREOS_PRIVATE_IPV4=${COREOS_PUBLIC_IPV4} block-until-url "${endpoint}" HOSTNAME="$(curl -Ls ${endpoint}/hostname)" +HOMEDIR="$(curl -Ls ${endpoint}/homedir)" ( echo endpoint=${endpoint} echo UUID=${UUID} echo HOSTNAME="${HOSTNAME}" + echo HOMEDIR="${HOMEDIR}" echo COREOS_PUBLIC_IPV4=${COREOS_PUBLIC_IPV4} echo COREOS_PRIVATE_IPV4=${COREOS_PRIVATE_IPV4} ) > /etc/environment sed -i "s,@@hostname@@,${HOSTNAME},g" /usr/share/oem/xhyve.yml +sed -i "s,@@homedir@@,${HOMEDIR},g" /usr/share/oem/xhyve.yml +sed -i "s,Users\.mount,$(systemd-escape -p ${HOMEDIR})\.mount,g" /usr/share/oem/xhyve.yml echo "$(curl -Ls ${endpoint}/sshKey)" | update-ssh-keys -a proc-cmdline-ssh_internal @@ -322,8 +326,8 @@ coreos: command: start content: | [Mount] - What=192.168.64.1:/Users - Where=/Users + What=192.168.64.1:@@homedir@@ + Where=@@homedir@@ Options=rw,async,nolock,noatime,rsize=32768,wsize=32768 Type=nfs ` diff --git a/helpers.go b/helpers.go index 44e6b24..5423e3e 100644 --- a/helpers.go +++ b/helpers.go @@ -267,7 +267,7 @@ func (session *sessionContext) init() (err error) { session.runDir = filepath.Join(session.configDir, "/running/") session.uid, session.gid = caller.Uid, caller.Gid - session.username = caller.Username + session.homedir = caller.HomeDir if session.pwd, err = os.Getwd(); err != nil { return @@ -387,6 +387,12 @@ func (vm *VMInfo) metadataService() (endpoint string, err error) { w.Write([]byte(vm.Name)) } }) + mux.HandleFunc(root+"/homedir", + func(w http.ResponseWriter, r *http.Request) { + if isAllowed(rIP(r.RemoteAddr), w) { + w.Write([]byte(engine.homedir)) + } + }) srv := &http.Server{ Addr: fmt.Sprintf(":%v", free.Addr().(*net.TCPAddr).Port), diff --git a/run.go b/run.go index 067b064..2969001 100644 --- a/run.go +++ b/run.go @@ -343,27 +343,23 @@ func init() { func nfsSetup() (err error) { const exportsF = "/etc/exports" var ( - buf []byte - shared bool - right string - shortSig = "/Users -network 192.168.64.0 " + + buf, bufN []byte + shared bool + oldSig = "/Users -network 192.168.64.0 " + "-mask 255.255.255.0 -alldirs -mapall=" suffix = engine.uid + ":" + engine.gid - signature = shortSig + suffix - exportSet = func() (ok bool, err error) { + signature = engine.homedir + " -network 192.168.64.0 " + + "-mask 255.255.255.0 -alldirs -mapall=" + suffix + exportSet = func() (ok bool) { for _, line := range strings.Split(string(buf), "\n") { - if strings.HasPrefix(line, shortSig) { - right = strings.Split(line, "=")[1] - if right != suffix { - err = fmt.Errorf("'/Users' is already being shared " + - "via NFS by another user other than the " + - "currently running one. Either keep invoking " + - "'corectl' as that user or manually fix your " + - "'/etc/exports' file") - break - } + if strings.HasPrefix(line, signature) { ok = true } + if !strings.HasPrefix(line, oldSig) { + bufN = append(bufN, []byte(line+"\n")...) + } else { + bufN = append(bufN, []byte("\n")...) + } } return } @@ -376,17 +372,17 @@ func nfsSetup() (err error) { } return false }() - exportsCheck = func() (err error) { + exportsCheck = func(previous []byte) (err error) { cmd := exec.Command("nfsd", "-F", exportsF, "checkexports") cmd.Stdin, cmd.Stdout, cmd.Stderr = nil, nil, os.Stderr if err = cmd.Run(); err != nil { err = fmt.Errorf("unable to validate %s (see above)", exportsF) // getting back to where we were - ioutil.WriteFile(exportsF, buf, os.ModeAppend) + ioutil.WriteFile(exportsF, previous, os.ModeAppend) } return - }() + } ) // check if /etc/exports exists, and if not create an empty one if _, err = os.Stat(exportsF); os.IsNotExist(err) { @@ -399,15 +395,13 @@ func nfsSetup() (err error) { return } - if shared, err = exportSet(); err != nil { - return + if shared = exportSet(); !shared { + ioutil.WriteFile(exportsF, append(bufN, []byte(signature)...), + os.ModeAppend) } - if !shared { - ioutil.WriteFile(exportsF, - append(buf, append([]byte("\n"), - append([]byte(signature), []byte("\n")...)...)...), - os.ModeAppend) + if err = exportsCheck(buf); err != nil { + return } if nfsIsRunning { @@ -416,16 +410,17 @@ func nfsSetup() (err error) { return fmt.Errorf("unable to update NFS "+ "service definitions... (%v)", err) } - log.Println("'/Users' was made available to VMs via NFS") + log.Printf("'%s' was made available to VMs via NFS\n", + engine.homedir) } } else { if err = exec.Command("nfsd", "start").Run(); err != nil { return fmt.Errorf("unable to start NFS service... (%v)", err) } - log.Println("NFS started in order for '/Users' to be " + - "made available to the VMs") + log.Printf("NFS started in order for '%s' to be "+ + "made available to the VMs\n", engine.homedir) } - return exportsCheck + return } func (vm *VMInfo) storeConfig() (err error) {