Browse code

Build, test, and CLI environment for OpenShift 3

Clayton Coleman authored on 2014/07/31 03:17:50
Showing 21 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+/output
1
+/pkg/version/autogenerated.go
2
+/third_party/pkg
... ...
@@ -1 +1,64 @@
1 1
 OpenShift Origin 3.0
2
+====================
3
+
4
+This is the source repository for the next version of OpenShift - the third architectural revision.  It is based around [Docker](https://www.docker.io) containers and images and the [Kubernetes](https://github.com/GoogleCloudPlatform/kubernetes) container management solution.  OpenShift adds developer  centric and organization centric workflows on top of Kubernetes, and much of the core functionality of OpenShift is designed as plugins to the core Kubernetes concepts.
5
+
6
+Please see the [OpenShift 3 Project Enhancement Proposal (PEP)](https://github.com/openshift/openshift-pep/blob/master/openshift-pep-013-openshift-3.md) for a deeper discussion of the features you see here.
7
+
8
+NOTE: This is a very early prototype, and as such is designed for rapid iteration around core concepts.
9
+
10
+Getting Started
11
+---------------
12
+
13
+You'll need Docker and the Go language compilation tools installed.
14
+
15
+1.  [Install Docker](https://docs.docker.com/installation/#installation)
16
+2.  [Install the Go language toolkit](http://golang.org/doc/install) and set your GOPATH
17
+3.  Clone this git repository through the Go tools:
18
+
19
+        $ go get github.com/openshift/origin
20
+        $ cd $GOPATH/src/github.com/openshift/origin
21
+   
22
+4.  Run a build
23
+
24
+        $ go get github.com/coreos/etcd
25
+        $ hack/build-go.sh
26
+    
27
+5.  Start an OpenShift all-in-one server (includes everything you need to try OpenShift)
28
+
29
+        $ output/go/bin/openshift start
30
+    
31
+6.  In another terminal window, switch to the directory:
32
+
33
+        $ cd $GOPATH/src/github.com/openshift/origin
34
+        $ output/go/bin/openshift kube create services -c examples/test-service.json
35
+    
36
+Coming soon: Vagrant environments supporting OpenShift - see [Kubernetes README.md](https://github.com/GoogleCloudPlatform/kubernetes/blob/master/README.md) for now.
37
+
38
+API
39
+---
40
+
41
+The OpenShift APIs are exposed at `http://localhost:8081/osapi/v1beta1/*`.  
42
+
43
+* `http://localhost:8080/api/v1beta1/services` (stub)
44
+
45
+The Kubernetes APIs are exposed at `http://localhost:8080/api/v1beta1/*`:
46
+
47
+* `http://localhost:8080/api/v1beta1/pods`
48
+* `http://localhost:8080/api/v1beta1/services`
49
+* `http://localhost:8080/api/v1beta1/replicationControllers`
50
+* `http://localhost:8080/api/v1beta1/operations`
51
+
52
+An draft of the proposed API is available [in this repository](https://rawgit.com/csrwng/oo-api-v3/master/oov3.html).  Expect significant changes.
53
+
54
+
55
+Contributing
56
+------------
57
+
58
+Contributions are welcome - a more formal process is coming soon.  In the meantime, open issues as necessary, ask questions on the OpenShift IRC channel (#openshift-dev on freenode), or get involved in the [Kubernetes project](https://github.com/GoogleCloudPlatform/kubernetes).
59
+
60
+
61
+License
62
+-------
63
+
64
+OpenShift is licensed under the Apache Software License 2.0.
2 65
\ No newline at end of file
3 66
new file mode 100644
... ...
@@ -0,0 +1,26 @@
0
+package main
1
+
2
+import (
3
+	"log"
4
+	"net/http"
5
+	"time"
6
+
7
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
8
+	"github.com/openshift/origin/pkg/api"
9
+	"github.com/openshift/origin/pkg/service"
10
+)
11
+
12
+func main() {
13
+	storage := map[string]apiserver.RESTStorage{
14
+		"services": service.NewRESTStorage(service.MakeMemoryRegistry()),
15
+	}
16
+
17
+	s := &http.Server{
18
+		Addr:           "127.0.0.1:8081",
19
+		Handler:        apiserver.New(storage, api.Codec, "/osapi/v1beta1"),
20
+		ReadTimeout:    10 * time.Second,
21
+		WriteTimeout:   10 * time.Second,
22
+		MaxHeaderBytes: 1 << 20,
23
+	}
24
+	log.Fatal(s.ListenAndServe())
25
+}
0 26
new file mode 100644
... ...
@@ -0,0 +1,62 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+
6
+	kubeversion "github.com/GoogleCloudPlatform/kubernetes/pkg/version"
7
+	"github.com/openshift/origin/pkg/cmd/client"
8
+	"github.com/openshift/origin/pkg/cmd/master"
9
+	"github.com/openshift/origin/pkg/version"
10
+	"github.com/spf13/cobra"
11
+)
12
+
13
+const longDescription = `
14
+OpenShift for Admins
15
+
16
+OpenShift helps you build, deploy, and manage your applications. To start an all-in-one server, run:
17
+
18
+    $ openshift start &
19
+    $ openshift kube create service -c examples/test-service.json
20
+
21
+OpenShift is built around Docker and the Kubernetes container orchestration service.  You must have
22
+Docker installed on this machine to start your server.
23
+
24
+Note: This is an alpha release of OpenShift and will change significantly.  See
25
+
26
+    https://github.com/openshift/origin
27
+
28
+for the latest information on OpenShift.
29
+
30
+`
31
+
32
+func main() {
33
+	openshiftCmd := &cobra.Command{
34
+		Use:   "openshift",
35
+		Short: "OpenShift helps you build, deploy, and manage your applications",
36
+		Long:  longDescription,
37
+		Run: func(c *cobra.Command, args []string) {
38
+			c.Help()
39
+		},
40
+	}
41
+
42
+	openshiftCmd.AddCommand(master.NewCommandStartAllInOne("start"))
43
+	openshiftCmd.AddCommand(client.NewCommandKubecfg("kube"))
44
+
45
+	// version information
46
+	versionCmd := &cobra.Command{
47
+		Use:   "version",
48
+		Short: "Display version",
49
+		Run: func(c *cobra.Command, args []string) {
50
+			major, minor, git := version.Get()
51
+			fmt.Printf("openshift version %s.%s, build %s\n", major, minor, git)
52
+			fmt.Printf("kubernetes %v\n", kubeversion.Get())
53
+		},
54
+	}
55
+	openshiftCmd.AddCommand(versionCmd)
56
+
57
+	if err := openshiftCmd.Execute(); err != nil {
58
+		fmt.Fprintf(os.Stderr, "Error: %s", err)
59
+		os.Exit(1)
60
+	}
61
+}
0 62
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+// This is the source repository for OpenShift Origin - the best way to build, manage, and deploy
1
+// applications in the cloud.  The OpenShift 3.0 codebase is based around Docker images and containers
2
+// and the Kubernetes container management system.
3
+package origin
0 4
new file mode 100644
... ...
@@ -0,0 +1,9 @@
0
+{
1
+  "id": "frontend",
2
+  "kind": "Service",
3
+  "apiVersion": "v1beta1",
4
+  "port": 9998,
5
+  "selector": {
6
+    "name": "frontend"
7
+  }
8
+}
0 9
new file mode 100755
... ...
@@ -0,0 +1,20 @@
0
+#!/bin/bash
1
+
2
+# This script sets up a go workspace locally and builds all go components.
3
+
4
+set -e
5
+
6
+# Update the version.
7
+$(dirname $0)/version-gen.sh
8
+
9
+source $(dirname $0)/config-go.sh
10
+
11
+cd "${OS_TARGET}"
12
+
13
+BINARIES="cmd/openshift"
14
+
15
+if [ $# -gt 0 ]; then
16
+  BINARIES="$@"
17
+fi
18
+
19
+go install $(for b in $BINARIES; do echo "${OS_GO_PACKAGE}"/${b}; done)
0 20
new file mode 100755
... ...
@@ -0,0 +1,72 @@
0
+#!/bin/bash
1
+
2
+# This script sets up a go workspace locally and builds all go components.
3
+# You can 'source' this file if you want to set up GOPATH in your local shell.
4
+
5
+if [ "$(which go)" == "" ]; then
6
+	echo "Can't find 'go' in PATH, please fix and retry."
7
+	echo "See http://golang.org/doc/install for installation instructions."
8
+	exit 1
9
+fi
10
+
11
+# Travis continuous build uses a head go release that doesn't report
12
+# a version number, so we skip this check on Travis.  Its unnecessary
13
+# there anyway.
14
+if [ "${TRAVIS}" != "true" ]; then
15
+  GO_VERSION=($(go version))
16
+
17
+  if [ ${GO_VERSION[2]} \< "go1.2" ]; then
18
+    echo "Detected go version: ${GO_VERSION}."
19
+    echo "OpenShift requires go version 1.2 or greater."
20
+    echo "Please install Go version 1.2 or later"
21
+    exit 1
22
+  fi
23
+fi
24
+
25
+pushd $(dirname "${BASH_SOURCE}")/.. >/dev/null
26
+OS_REPO_ROOT="${PWD}"
27
+OS_TARGET="${OS_REPO_ROOT}/output/go"
28
+popd >/dev/null
29
+
30
+mkdir -p "${OS_TARGET}"
31
+
32
+OLD_GOPATH="${GOPATH}"
33
+export GOPATH="${OS_TARGET}"
34
+
35
+OS_GO_PACKAGE="github.com/openshift/origin"
36
+OS_GO_PACKAGE_DIR="${GOPATH}/src/${OS_GO_PACKAGE}"
37
+
38
+ETCD_GO_PACKAGE="github.com/coreos/etcd"
39
+ETCD_GO_PACKAGE_DIR="${GOPATH}/src/${ETCD_GO_PACKAGE}"
40
+if [ ! -d "${OLD_GOPATH}/src/${ETCD_GO_PACKAGE}" ]; then
41
+  echo "You must go get ${ETCD_GO_PACKAGE}"
42
+fi
43
+
44
+(
45
+  PACKAGE_BASE=$(dirname "${OS_GO_PACKAGE_DIR}")
46
+  if [ ! -d "${PACKAGE_BASE}" ]; then
47
+    mkdir -p "${PACKAGE_BASE}"
48
+  fi
49
+  rm "${OS_GO_PACKAGE_DIR}" >/dev/null 2>&1 || true
50
+  ln -s "${OS_REPO_ROOT}" "${OS_GO_PACKAGE_DIR}"
51
+
52
+  PACKAGE_BASE=$(dirname "${ETCD_GO_PACKAGE_DIR}")
53
+  if [ ! -d "${PACKAGE_BASE}" ]; then
54
+    mkdir -p "${PACKAGE_BASE}"
55
+  fi
56
+  rm "${ETCD_GO_PACKAGE_DIR}" >/dev/null 2>&1 || true
57
+  ln -s "${OLD_GOPATH}/src/${ETCD_GO_PACKAGE}" "${ETCD_GO_PACKAGE_DIR}"
58
+
59
+
60
+  if [[ "$OS_KUBE_PATH" != "" ]]; then
61
+    echo "Using Kubernetes from source $OS_KUBE_PATH"
62
+    OS_GO_KUBE_PACKAGE_DIR="${OS_TARGET}/src/github.com/GoogleCloudPlatform/kubernetes"
63
+    KUBE_PACKAGE_BASE=$(dirname "${OS_GO_KUBE_PACKAGE_DIR}")
64
+    if [ ! -d "${KUBE_PACKAGE_BASE}" ]; then
65
+      mkdir -p "${KUBE_PACKAGE_BASE}"
66
+    fi
67
+    rm "${OS_GO_KUBE_PACKAGE_DIR}" >/dev/null 2>&1 || true
68
+    ln -s "${OS_KUBE_PATH}" "${OS_GO_KUBE_PACKAGE_DIR}"
69
+  fi
70
+)
71
+export GOPATH="${OS_TARGET}:${OS_REPO_ROOT}/third_party/src/github.com/GoogleCloudPlatform/kubernetes/third_party:${OS_REPO_ROOT}/third_party"
0 72
new file mode 100755
... ...
@@ -0,0 +1,35 @@
0
+#!/bin/bash
1
+
2
+set -e
3
+
4
+source $(dirname $0)/config-go.sh
5
+
6
+
7
+find_test_dirs() {
8
+  (
9
+    cd src/${OS_GO_PACKAGE}
10
+    find . -not \( \
11
+        \( \
12
+          -wholename './third_party' \
13
+          -o -wholename './release' \
14
+          -o -wholename './target' \
15
+          -o -wholename '*/third_party/*' \
16
+          -o -wholename '*/output/*' \
17
+        \) -prune \
18
+      \) -name '*_test.go' -print0 | xargs -0n1 dirname | sort -u
19
+  )
20
+}
21
+
22
+# -covermode=atomic becomes default with -race in Go >=1.3
23
+COVER="-cover -covermode=atomic -coverprofile=tmp.out"
24
+
25
+cd "${OS_TARGET}"
26
+
27
+if [ "$1" != "" ]; then
28
+  go test -race -timeout 30s $COVER "$OS_GO_PACKAGE/$1" "${@:2}"
29
+  exit 0
30
+fi
31
+
32
+for package in $(find_test_dirs); do
33
+  go test -race -timeout 30s $COVER "${OS_GO_PACKAGE}/${package}" "${@:2}"
34
+done
0 35
new file mode 100755
... ...
@@ -0,0 +1,11 @@
0
+#!/bin/bash
1
+
2
+$(dirname $0)/../third_party/src/github.com/GoogleCloudPlatform/kubernetes/hack/version-gen.sh
3
+
4
+# TODO: when we start making tags, switch to git describe?
5
+desc=$(git rev-list --abbrev-commit --max-count=1 HEAD)
6
+tab=$'\t'
7
+script="6s/.*/${tab}commitFromGit = \`${desc}\`/"
8
+infile="$(dirname $0)/../pkg/version/template.go"
9
+outfile="$(dirname $0)/../pkg/version/autogenerated.go"
10
+sed "${script}" "${infile}" > "${outfile}"
0 11
new file mode 100644
... ...
@@ -0,0 +1,86 @@
0
+package api
1
+
2
+import (
3
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
4
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
5
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
6
+)
7
+
8
+type ServiceList struct {
9
+	api.JSONBase `json:",inline" yaml:",inline"`
10
+	Items        []Service `json:"items" yaml:"items,omitempty"`
11
+}
12
+
13
+type Service struct {
14
+	api.JSONBase `json:",inline" yaml:",inline"`
15
+	Labels       map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
16
+}
17
+
18
+// codec defines methods for serializing and deserializing API
19
+// objects
20
+type codec interface {
21
+	Encode(obj interface{}) (data []byte, err error)
22
+	Decode(data []byte) (interface{}, error)
23
+	DecodeInto(data []byte, obj interface{}) error
24
+}
25
+
26
+// resourceVersioner provides methods for setting and retrieving
27
+// the resource version from an API object
28
+type resourceVersioner interface {
29
+	SetResourceVersion(obj interface{}, version uint64) error
30
+	ResourceVersion(obj interface{}) (uint64, error)
31
+}
32
+
33
+var Codec codec
34
+var ResourceVersioner resourceVersioner
35
+
36
+var scheme *conversion.Scheme
37
+
38
+func init() {
39
+	scheme = conversion.NewScheme()
40
+	scheme.InternalVersion = ""
41
+	scheme.ExternalVersion = "v1beta1"
42
+	scheme.MetaInsertionFactory = metaInsertion{}
43
+	scheme.AddKnownTypes("",
44
+		ServiceList{},
45
+		Service{},
46
+		api.Status{},
47
+		api.ServerOp{},
48
+		api.ServerOpList{},
49
+	)
50
+	scheme.AddKnownTypes("v1beta1",
51
+		ServiceList{},
52
+		Service{},
53
+		v1beta1.Status{},
54
+		v1beta1.ServerOp{},
55
+		v1beta1.ServerOpList{},
56
+	)
57
+
58
+	Codec = scheme
59
+	ResourceVersioner = api.NewJSONBaseResourceVersioner()
60
+}
61
+
62
+// metaInsertion implements conversion.MetaInsertionFactory, which lets the conversion
63
+// package figure out how to encode our object's types and versions. These fields are
64
+// located in our JSONBase.
65
+type metaInsertion struct {
66
+	JSONBase struct {
67
+		APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
68
+		Kind       string `json:"kind,omitempty" yaml:"kind,omitempty"`
69
+	} `json:",inline" yaml:",inline"`
70
+}
71
+
72
+// Create returns a new metaInsertion with the version and kind fields set.
73
+func (metaInsertion) Create(version, kind string) interface{} {
74
+	m := metaInsertion{}
75
+	m.JSONBase.APIVersion = version
76
+	m.JSONBase.Kind = kind
77
+	return &m
78
+}
79
+
80
+// Interpret returns the version and kind information from in, which must be
81
+// a metaInsertion pointer object.
82
+func (metaInsertion) Interpret(in interface{}) (version, kind string) {
83
+	m := in.(*metaInsertion)
84
+	return m.JSONBase.APIVersion, m.JSONBase.Kind
85
+}
0 86
new file mode 100644
... ...
@@ -0,0 +1,49 @@
0
+package client
1
+
2
+import (
3
+	"os"
4
+	"time"
5
+
6
+	"github.com/spf13/cobra"
7
+)
8
+
9
+const longDescription = `
10
+Kubernetes Command Line - kubecfg
11
+
12
+OpenShift currently embeds the kubecfg command line for prototyping and debugging.
13
+`
14
+
15
+func NewCommandKubecfg(name string) *cobra.Command {
16
+	cfg := &KubeConfig{}
17
+	cmd := &cobra.Command{
18
+		Use:   name,
19
+		Short: "The Kubernetes command line client",
20
+		Long:  longDescription + usage(name),
21
+		Run: func(c *cobra.Command, args []string) {
22
+			if len(args) < 1 {
23
+				c.Help()
24
+				os.Exit(1)
25
+			}
26
+			cfg.Args = args
27
+			cfg.Run()
28
+		},
29
+	}
30
+	flag := cmd.Flags()
31
+	flag.BoolVar(&cfg.ServerVersion, "server_version", false, "Print the server's version number.")
32
+	flag.BoolVar(&cfg.PreventSkew, "expect_version_match", false, "Fail if server's version doesn't match own version.")
33
+	flag.StringVarP(&cfg.HttpServer, "host", "h", "", "The host to connect to.")
34
+	flag.StringVarP(&cfg.Config, "config", "c", "", "Path to the config file.")
35
+	flag.StringVarP(&cfg.Selector, "label", "l", "", "Selector (label query) to use for listing")
36
+	flag.DurationVarP(&cfg.UpdatePeriod, "update", "u", 60*time.Second, "Update interval period")
37
+	flag.StringVarP(&cfg.PortSpec, "port", "p", "", "The port spec, comma-separated list of <external>:<internal>,...")
38
+	flag.IntVarP(&cfg.ServicePort, "service", "s", -1, "If positive, create and run a corresponding service on this port, only used with 'run'")
39
+	flag.StringVar(&cfg.AuthConfig, "auth", os.Getenv("HOME")+"/.kubernetes_auth", "Path to the auth info file.  If missing, prompt the user.  Only used if doing https.")
40
+	flag.BoolVar(&cfg.JSON, "json", false, "If true, print raw JSON for responses")
41
+	flag.BoolVar(&cfg.YAML, "yaml", false, "If true, print raw YAML for responses")
42
+	flag.BoolVar(&cfg.Verbose, "verbose", false, "If true, print extra information")
43
+	flag.BoolVar(&cfg.Proxy, "proxy", false, "If true, run a proxy to the api server")
44
+	flag.StringVar(&cfg.WWW, "www", "", "If -proxy is true, use this directory to serve static files")
45
+	flag.StringVar(&cfg.TemplateFile, "template_file", "", "If present, load this file as a golang template and use it for output printing")
46
+	flag.StringVar(&cfg.TemplateStr, "template", "", "If present, parse this string as a golang template and use it for output printing")
47
+	return cmd
48
+}
0 49
new file mode 100644
... ...
@@ -0,0 +1,355 @@
0
+/*
1
+Copyright 2014 Google Inc. All rights reserved.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+    http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+package client
17
+
18
+import (
19
+	"fmt"
20
+	"io/ioutil"
21
+	"net/url"
22
+	"os"
23
+	"reflect"
24
+	"sort"
25
+	"strconv"
26
+	"strings"
27
+	"text/template"
28
+	"time"
29
+
30
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
31
+	kubeclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
32
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubecfg"
33
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
34
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/version"
35
+	"github.com/golang/glog"
36
+)
37
+
38
+type KubeConfig struct {
39
+	ServerVersion bool
40
+	PreventSkew   bool
41
+	HttpServer    string
42
+	Config        string
43
+	Selector      string
44
+	UpdatePeriod  time.Duration
45
+	PortSpec      string
46
+	ServicePort   int
47
+	AuthConfig    string
48
+	JSON          bool
49
+	YAML          bool
50
+	Verbose       bool
51
+	Proxy         bool
52
+	WWW           string
53
+	TemplateFile  string
54
+	TemplateStr   string
55
+
56
+	Args []string
57
+}
58
+
59
+func (c *KubeConfig) Arg(index int) string {
60
+	if index >= len(c.Args) {
61
+		return ""
62
+	}
63
+	return c.Args[index]
64
+}
65
+
66
+func usage(name string) string {
67
+	return fmt.Sprintf(`
68
+  Kubernetes REST API:
69
+  %[1]s [OPTIONS] get|list|create|delete|update <%[2]s>[/<id>]
70
+
71
+  Manage replication controllers:
72
+  %[1]s [OPTIONS] stop|rm|rollingupdate <controller>
73
+  %[1]s [OPTIONS] run <image> <replicas> <controller>
74
+  %[1]s [OPTIONS] resize <controller> <replicas>
75
+`, name, prettyWireStorage())
76
+}
77
+
78
+func prettyWireStorage() string {
79
+	types := kubecfg.SupportedWireStorage()
80
+	sort.Strings(types)
81
+	return strings.Join(types, "|")
82
+}
83
+
84
+// readConfig reads and parses pod, replicationController, and service
85
+// configuration files. If any errors log and exit non-zero.
86
+func (c *KubeConfig) readConfig(storage string) []byte {
87
+	if len(c.Config) == 0 {
88
+		glog.Fatal("Need config file (-c)")
89
+	}
90
+	data, err := ioutil.ReadFile(c.Config)
91
+	if err != nil {
92
+		glog.Fatalf("Unable to read %v: %v\n", c.Config, err)
93
+	}
94
+	data, err = kubecfg.ToWireFormat(data, storage)
95
+	if err != nil {
96
+		glog.Fatalf("Error parsing %v as an object for %v: %v\n", c.Config, storage, err)
97
+	}
98
+	if c.Verbose {
99
+		glog.Infof("Parsed config file successfully; sending:\n%v\n", string(data))
100
+	}
101
+	return data
102
+}
103
+
104
+func (c *KubeConfig) Run() {
105
+	util.InitLogs()
106
+	defer util.FlushLogs()
107
+
108
+	secure := true
109
+	var masterServer string
110
+	if len(c.HttpServer) > 0 {
111
+		masterServer = c.HttpServer
112
+	} else if len(os.Getenv("KUBERNETES_MASTER")) > 0 {
113
+		masterServer = os.Getenv("KUBERNETES_MASTER")
114
+	} else {
115
+		masterServer = "http://localhost:8080"
116
+	}
117
+	parsedURL, err := url.Parse(masterServer)
118
+	if err != nil {
119
+		glog.Fatalf("Unable to parse %v as a URL\n", err)
120
+	}
121
+	if parsedURL.Scheme != "" && parsedURL.Scheme != "https" {
122
+		secure = false
123
+	}
124
+
125
+	var auth *kubeclient.AuthInfo
126
+	if secure {
127
+		auth, err = kubecfg.LoadAuthInfo(c.AuthConfig, os.Stdin)
128
+		if err != nil {
129
+			glog.Fatalf("Error loading auth: %v", err)
130
+		}
131
+	}
132
+
133
+	client := kubeclient.New(masterServer, auth)
134
+
135
+	if c.ServerVersion {
136
+		got, err := client.ServerVersion()
137
+		if err != nil {
138
+			fmt.Printf("Couldn't read version from server: %v\n", err)
139
+			os.Exit(1)
140
+		}
141
+		fmt.Printf("Server Version: %#v\n", got)
142
+		os.Exit(0)
143
+	}
144
+
145
+	if c.PreventSkew {
146
+		got, err := client.ServerVersion()
147
+		if err != nil {
148
+			fmt.Printf("Couldn't read version from server: %v\n", err)
149
+			os.Exit(1)
150
+		}
151
+		if c, s := version.Get(), *got; !reflect.DeepEqual(c, s) {
152
+			fmt.Printf("Server version (%#v) differs from client version (%#v)!\n", s, c)
153
+			os.Exit(1)
154
+		}
155
+	}
156
+
157
+	if c.Proxy {
158
+		glog.Info("Starting to serve on localhost:8001")
159
+		server := kubecfg.NewProxyServer(c.WWW, masterServer, auth)
160
+		glog.Fatal(server.Serve())
161
+	}
162
+
163
+	method := c.Arg(0)
164
+
165
+	matchFound := c.executeAPIRequest(method, client) || c.executeControllerRequest(method, client)
166
+	if matchFound == false {
167
+		glog.Fatalf("Unknown command %s", method)
168
+	}
169
+}
170
+
171
+// storagePathFromArg normalizes a path and breaks out the first segment if available
172
+func storagePathFromArg(arg string) (storage, path string, hasSuffix bool) {
173
+	path = strings.Trim(arg, "/")
174
+	segments := strings.SplitN(path, "/", 2)
175
+	storage = segments[0]
176
+	if len(segments) > 1 && segments[1] != "" {
177
+		hasSuffix = true
178
+	}
179
+	return storage, path, hasSuffix
180
+}
181
+
182
+//checkStorage returns true if the provided storage is valid
183
+func checkStorage(storage string) bool {
184
+	for _, allowed := range kubecfg.SupportedWireStorage() {
185
+		if allowed == storage {
186
+			return true
187
+		}
188
+	}
189
+	return false
190
+}
191
+
192
+func (c *KubeConfig) executeAPIRequest(method string, client *kubeclient.Client) bool {
193
+	storage, path, hasSuffix := storagePathFromArg(c.Arg(1))
194
+	validStorage := checkStorage(storage)
195
+	verb := ""
196
+	setBody := false
197
+	var version uint64
198
+	switch method {
199
+	case "get":
200
+		verb = "GET"
201
+		if !validStorage || !hasSuffix {
202
+			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>[/<id>]", method, prettyWireStorage())
203
+		}
204
+	case "list":
205
+		verb = "GET"
206
+		if !validStorage || hasSuffix {
207
+			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage())
208
+		}
209
+	case "delete":
210
+		verb = "DELETE"
211
+		if !validStorage || !hasSuffix {
212
+			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
213
+		}
214
+	case "create":
215
+		verb = "POST"
216
+		setBody = true
217
+		if !validStorage || hasSuffix {
218
+			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage())
219
+		}
220
+	case "update":
221
+		obj, err := client.Verb("GET").Path(path).Do().Get()
222
+		if err != nil {
223
+			glog.Fatalf("error obtaining resource version for update: %v", err)
224
+		}
225
+		jsonBase, err := api.FindJSONBase(obj)
226
+		if err != nil {
227
+			glog.Fatalf("error finding json base for update: %v", err)
228
+		}
229
+		version = jsonBase.ResourceVersion()
230
+		verb = "PUT"
231
+		setBody = true
232
+		if !validStorage || !hasSuffix {
233
+			glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage())
234
+		}
235
+	default:
236
+		return false
237
+	}
238
+
239
+	r := client.Verb(verb).
240
+		Path(path).
241
+		ParseSelector(c.Selector)
242
+	if setBody {
243
+		if version != 0 {
244
+			data := c.readConfig(storage)
245
+			obj, err := api.Decode(data)
246
+			if err != nil {
247
+				glog.Fatalf("error setting resource version: %v", err)
248
+			}
249
+			jsonBase, err := api.FindJSONBase(obj)
250
+			if err != nil {
251
+				glog.Fatalf("error setting resource version: %v", err)
252
+			}
253
+			jsonBase.SetResourceVersion(version)
254
+			data, err = api.Encode(obj)
255
+			if err != nil {
256
+				glog.Fatalf("error setting resource version: %v", err)
257
+			}
258
+			r.Body(data)
259
+		} else {
260
+			r.Body(c.readConfig(storage))
261
+		}
262
+	}
263
+	result := r.Do()
264
+	obj, err := result.Get()
265
+	if err != nil {
266
+		glog.Fatalf("Got request error: %v\n", err)
267
+		return false
268
+	}
269
+
270
+	var printer kubecfg.ResourcePrinter
271
+	switch {
272
+	case c.JSON:
273
+		printer = &kubecfg.IdentityPrinter{}
274
+	case c.YAML:
275
+		printer = &kubecfg.YAMLPrinter{}
276
+	case len(c.TemplateFile) > 0 || len(c.TemplateStr) > 0:
277
+		var data []byte
278
+		if len(c.TemplateFile) > 0 {
279
+			var err error
280
+			data, err = ioutil.ReadFile(c.TemplateFile)
281
+			if err != nil {
282
+				glog.Fatalf("Error reading template %s, %v\n", c.TemplateFile, err)
283
+				return false
284
+			}
285
+		} else {
286
+			data = []byte(c.TemplateStr)
287
+		}
288
+		tmpl, err := template.New("output").Parse(string(data))
289
+		if err != nil {
290
+			glog.Fatalf("Error parsing template %s, %v\n", string(data), err)
291
+			return false
292
+		}
293
+		printer = &kubecfg.TemplatePrinter{
294
+			Template: tmpl,
295
+		}
296
+	default:
297
+		printer = &kubecfg.HumanReadablePrinter{}
298
+	}
299
+
300
+	if err = printer.PrintObj(obj, os.Stdout); err != nil {
301
+		body, _ := result.Raw()
302
+		glog.Fatalf("Failed to print: %v\nRaw received object:\n%#v\n\nBody received: %v", err, obj, string(body))
303
+	}
304
+	fmt.Print("\n")
305
+
306
+	return true
307
+}
308
+
309
+func (c *KubeConfig) executeControllerRequest(method string, client *kubeclient.Client) bool {
310
+	parseController := func() string {
311
+		if len(c.Args) != 2 {
312
+			glog.Fatal("usage: kubecfg [OPTIONS] stop|rm|rollingupdate <controller>")
313
+		}
314
+		return c.Arg(1)
315
+	}
316
+
317
+	var err error
318
+	switch method {
319
+	case "stop":
320
+		err = kubecfg.StopController(parseController(), client)
321
+	case "rm":
322
+		err = kubecfg.DeleteController(parseController(), client)
323
+	case "rollingupdate":
324
+		err = kubecfg.Update(parseController(), client, c.UpdatePeriod)
325
+	case "run":
326
+		if len(c.Args) != 4 {
327
+			glog.Fatal("usage: kubecfg [OPTIONS] run <image> <replicas> <controller>")
328
+		}
329
+		image := c.Arg(1)
330
+		replicas, err := strconv.Atoi(c.Arg(2))
331
+		name := c.Arg(3)
332
+		if err != nil {
333
+			glog.Fatalf("Error parsing replicas: %v", err)
334
+		}
335
+		err = kubecfg.RunController(image, name, replicas, client, c.PortSpec, c.ServicePort)
336
+	case "resize":
337
+		args := c.Args
338
+		if len(args) < 3 {
339
+			glog.Fatal("usage: kubecfg resize <controller> <replicas>")
340
+		}
341
+		name := args[1]
342
+		replicas, err := strconv.Atoi(args[2])
343
+		if err != nil {
344
+			glog.Fatalf("Error parsing replicas: %v", err)
345
+		}
346
+		err = kubecfg.ResizeController(name, replicas, client)
347
+	default:
348
+		return false
349
+	}
350
+	if err != nil {
351
+		glog.Fatalf("Error: %v", err)
352
+	}
353
+	return true
354
+}
0 355
new file mode 100644
... ...
@@ -0,0 +1,162 @@
0
+package master
1
+
2
+import (
3
+	"fmt"
4
+	"net/http"
5
+	"os"
6
+	"path"
7
+	"time"
8
+
9
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
10
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
11
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
12
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
13
+	kconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
14
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
15
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/proxy"
16
+	pconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/proxy/config"
17
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
18
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
19
+	etcdconfig "github.com/coreos/etcd/config"
20
+	"github.com/coreos/etcd/etcd"
21
+	etcdclient "github.com/coreos/go-etcd/etcd"
22
+	"github.com/fsouza/go-dockerclient"
23
+	"github.com/golang/glog"
24
+	"github.com/google/cadvisor/client"
25
+	"github.com/openshift/origin/pkg/api"
26
+	"github.com/openshift/origin/pkg/service"
27
+	"github.com/spf13/cobra"
28
+)
29
+
30
+func NewCommandStartAllInOne(name string) *cobra.Command {
31
+	return &cobra.Command{
32
+		Use:   name,
33
+		Short: "Launch in all-in-one mode",
34
+		Run: func(c *cobra.Command, args []string) {
35
+			startAllInOne()
36
+		},
37
+	}
38
+}
39
+
40
+func startAllInOne() {
41
+	dockerAddr := getDockerEndpoint("")
42
+	dockerClient, err := docker.NewClient(dockerAddr)
43
+	if err != nil {
44
+		glog.Fatal("Couldn't connect to docker.")
45
+	}
46
+	if err := dockerClient.Ping(); err != nil {
47
+		glog.Errorf("WARNING: Docker could not be reached at %s.  Docker must be installed and running to start containers.\n%v", dockerAddr, err)
48
+	}
49
+
50
+	cadvisorClient, err := cadvisor.NewClient("http://127.0.0.1:4194")
51
+	if err != nil {
52
+		glog.Errorf("Error on creating cadvisor client: %v", err)
53
+	}
54
+
55
+	// initialize etcd
56
+	etcdAddr := "127.0.0.1:4001"
57
+	etcdServers := []string{} // default
58
+	etcdConfig := etcdconfig.New()
59
+	etcdConfig.BindAddr = etcdAddr
60
+	etcdServer := etcd.New(etcdConfig)
61
+	go util.Forever(func() { etcdServer.Run() }, 0)
62
+	glog.Infof("Started etcd at http://%s", etcdAddr)
63
+
64
+	etcdClient := etcdclient.NewClient(etcdServers)
65
+	for i := 0; ; i += 1 {
66
+		_, err := etcdClient.Get("/", false, false)
67
+		if err == nil || tools.IsEtcdNotFound(err) {
68
+			break
69
+		}
70
+		if i > 100 {
71
+			glog.Fatal("Could not reach etcd: %v", err)
72
+		}
73
+		time.Sleep(50 * time.Millisecond)
74
+	}
75
+
76
+	// initialize Kubelet
77
+	minionHost := "127.0.0.1"
78
+	minionPort := 10250
79
+	rootDirectory := path.Clean("/var/lib/openshift")
80
+	os.MkdirAll(rootDirectory, 0750)
81
+	cfg := kconfig.NewPodConfig(kconfig.PodConfigNotificationSnapshotAndUpdates)
82
+	kconfig.NewSourceEtcd(kconfig.EtcdKeyForHost(minionHost), etcdClient, 30*time.Second, cfg.Channel("etcd"))
83
+	k := kubelet.NewMainKubelet(
84
+		minionHost,
85
+		dockerClient,
86
+		cadvisorClient,
87
+		etcdClient,
88
+		rootDirectory)
89
+	go util.Forever(func() { k.Run(cfg.Updates()) }, 0)
90
+	go util.Forever(func() {
91
+		kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), http.DefaultServeMux, minionHost, uint(minionPort))
92
+	}, 0)
93
+
94
+	// initialize OpenShift API
95
+	storage := map[string]apiserver.RESTStorage{
96
+		"services": service.NewRESTStorage(service.MakeMemoryRegistry()),
97
+	}
98
+	osAddr := "127.0.0.1:8081"
99
+	osPrefix := "/osapi/v1beta1"
100
+	osApi := &http.Server{
101
+		Addr:           osAddr,
102
+		Handler:        apiserver.New(storage, api.Codec, osPrefix),
103
+		ReadTimeout:    10 * time.Second,
104
+		WriteTimeout:   10 * time.Second,
105
+		MaxHeaderBytes: 1 << 20,
106
+	}
107
+	go util.Forever(func() { glog.Fatal(osApi.ListenAndServe()) }, 0)
108
+	glog.Infof("Started OpenShift API at http://%s%s", osAddr, osPrefix)
109
+
110
+	// initialize Kubernetes API
111
+	kubeAddr := "127.0.0.1:8080"
112
+	kubePrefix := "/api/v1beta1"
113
+	kubeClient := client.New(fmt.Sprintf("http://%s", kubeAddr), nil)
114
+	podInfoGetter := &client.HTTPPodInfoGetter{
115
+		Client: http.DefaultClient,
116
+		Port:   uint(minionPort),
117
+	}
118
+	masterConfig := &master.Config{
119
+		Client:             kubeClient,
120
+		EtcdServers:        etcdServers,
121
+		HealthCheckMinions: true,
122
+		Minions:            []string{minionHost},
123
+		PodInfoGetter:      podInfoGetter,
124
+	}
125
+	m := master.New(masterConfig)
126
+	go util.Forever(func() { m.Run(kubeAddr, kubePrefix) }, 0)
127
+	glog.Infof("Started Kubernetes API at http://%s%s", kubeAddr, kubePrefix)
128
+
129
+	// initialize kube proxy
130
+	serviceConfig := pconfig.NewServiceConfig()
131
+	endpointsConfig := pconfig.NewEndpointsConfig()
132
+	pconfig.NewConfigSourceEtcd(etcdClient,
133
+		serviceConfig.Channel("etcd"),
134
+		endpointsConfig.Channel("etcd"))
135
+	loadBalancer := proxy.NewLoadBalancerRR()
136
+	proxier := proxy.NewProxier(loadBalancer)
137
+	serviceConfig.RegisterHandler(proxier)
138
+	endpointsConfig.RegisterHandler(loadBalancer)
139
+	glog.Infof("Started Kubernetes Proxy")
140
+
141
+	// initialize replication manager
142
+	controllerManager := controller.MakeReplicationManager(kubeClient)
143
+	controllerManager.Run(10 * time.Second)
144
+	glog.Infof("Started Kubernetes Replication Manager")
145
+
146
+	select {}
147
+}
148
+
149
+func getDockerEndpoint(dockerEndpoint string) string {
150
+	var endpoint string
151
+	if len(dockerEndpoint) > 0 {
152
+		endpoint = dockerEndpoint
153
+	} else if len(os.Getenv("DOCKER_HOST")) > 0 {
154
+		endpoint = os.Getenv("DOCKER_HOST")
155
+	} else {
156
+		endpoint = "unix:///var/run/docker.sock"
157
+	}
158
+	glog.Infof("Connecting to docker on %s", endpoint)
159
+
160
+	return endpoint
161
+}
0 162
new file mode 100644
... ...
@@ -0,0 +1,19 @@
0
+package service
1
+
2
+import (
3
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
4
+	"github.com/openshift/origin/pkg/api"
5
+)
6
+
7
+// ServiceRegistry is an interface implemented by things that know how to store Service objects.
8
+type ServiceRegistry interface {
9
+	// ListServices obtains a list of services that match selector.
10
+	ListServices(selector labels.Selector) ([]api.Service, error)
11
+	// Get a specific service
12
+	GetService(serviceID string) (*api.Service, error)
13
+	CreateService(service api.Service) error
14
+	// Update an existing service
15
+	UpdateService(service api.Service) error
16
+	// Delete an existing service
17
+	DeleteService(serviceID string) error
18
+}
0 19
new file mode 100644
... ...
@@ -0,0 +1,51 @@
0
+package service
1
+
2
+import (
3
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
4
+	"github.com/openshift/origin/pkg/api"
5
+)
6
+
7
+// Mainly used for testing.
8
+type MemoryRegistry struct {
9
+	serviceData map[string]api.Service
10
+}
11
+
12
+func MakeMemoryRegistry() *MemoryRegistry {
13
+	return &MemoryRegistry{
14
+		serviceData: map[string]api.Service{},
15
+	}
16
+}
17
+
18
+func (registry *MemoryRegistry) ListServices(selector labels.Selector) ([]api.Service, error) {
19
+	result := []api.Service{}
20
+	for _, value := range registry.serviceData {
21
+		if selector.Matches(labels.Set(value.Labels)) {
22
+			result = append(result, value)
23
+		}
24
+	}
25
+	return result, nil
26
+}
27
+
28
+func (registry *MemoryRegistry) GetService(serviceID string) (*api.Service, error) {
29
+	service, found := registry.serviceData[serviceID]
30
+	if found {
31
+		return &service, nil
32
+	} else {
33
+		return nil, nil
34
+	}
35
+}
36
+
37
+func (registry *MemoryRegistry) CreateService(service api.Service) error {
38
+	registry.serviceData[service.ID] = service
39
+	return nil
40
+}
41
+
42
+func (registry *MemoryRegistry) DeleteService(serviceID string) error {
43
+	delete(registry.serviceData, serviceID)
44
+	return nil
45
+}
46
+
47
+func (registry *MemoryRegistry) UpdateService(service api.Service) error {
48
+	registry.serviceData[service.ID] = service
49
+	return nil
50
+}
0 51
new file mode 100644
... ...
@@ -0,0 +1,77 @@
0
+package service
1
+
2
+import (
3
+	"fmt"
4
+
5
+	baseapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
6
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
7
+	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
8
+	"github.com/openshift/origin/pkg/api"
9
+)
10
+
11
+type ServiceRegistryStorage struct {
12
+	registry ServiceRegistry
13
+}
14
+
15
+func NewRESTStorage(registry ServiceRegistry) apiserver.RESTStorage {
16
+	return &ServiceRegistryStorage{registry}
17
+}
18
+
19
+func (s *ServiceRegistryStorage) New() interface{} {
20
+	return &api.Service{}
21
+}
22
+
23
+func (s *ServiceRegistryStorage) Get(id string) (interface{}, error) {
24
+	service, err := s.registry.GetService(id)
25
+	if err != nil {
26
+		return service, err
27
+	}
28
+	if service == nil {
29
+		return service, nil
30
+	}
31
+	return service, err
32
+}
33
+
34
+func (s *ServiceRegistryStorage) List(selector labels.Selector) (interface{}, error) {
35
+	var result api.ServiceList
36
+	services, err := s.registry.ListServices(selector)
37
+	if err == nil {
38
+		result.Items = services
39
+	}
40
+	return result, err
41
+}
42
+
43
+func (s *ServiceRegistryStorage) Delete(id string) (<-chan interface{}, error) {
44
+	return apiserver.MakeAsync(func() (interface{}, error) {
45
+		return baseapi.Status{Status: baseapi.StatusSuccess}, s.registry.DeleteService(id)
46
+	}), nil
47
+}
48
+
49
+func (s *ServiceRegistryStorage) Create(obj interface{}) (<-chan interface{}, error) {
50
+	service := obj.(api.Service)
51
+	if len(service.ID) == 0 {
52
+		return nil, fmt.Errorf("id is unspecified: %#v", service)
53
+	}
54
+
55
+	return apiserver.MakeAsync(func() (interface{}, error) {
56
+		if err := s.registry.CreateService(service); err != nil {
57
+			return nil, err
58
+		}
59
+		return s.Get(service.ID)
60
+	}), nil
61
+}
62
+
63
+func (s *ServiceRegistryStorage) Update(obj interface{}) (<-chan interface{}, error) {
64
+	service := obj.(api.Service)
65
+	if len(service.ID) == 0 {
66
+		return nil, fmt.Errorf("id is unspecified: %#v", service)
67
+	}
68
+
69
+	return apiserver.MakeAsync(func() (interface{}, error) {
70
+		err := s.registry.UpdateService(service)
71
+		if err != nil {
72
+			return nil, err
73
+		}
74
+		return s.Get(service.ID)
75
+	}), nil
76
+}
0 77
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+package version
1
+
2
+// This file is the template for the machine-edited autogenerated.go.
3
+// Do not modify this file without also modifying hack/version-gen.sh.
4
+var (
5
+	placeholder interface{}
6
+)
0 7
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+package version
1
+
2
+func Get() (major, minor, gitCommit string) {
3
+	return "0", "1", commitFromGit
4
+}
0 5
new file mode 100755
... ...
@@ -0,0 +1,11 @@
0
+TOP_PACKAGES="
1
+  github.com/GoogleCloudPlatform/kubernetes
2
+  github.com/spf13/cobra
3
+"
4
+
5
+DEP_PACKAGES="
6
+  github.com/spf13/pflag
7
+  github.com/coreos/go-etcd
8
+"
9
+
10
+PACKAGES="$TOP_PACKAGES $DEP_PACKAGES"
0 11
\ No newline at end of file
1 12
new file mode 100755
... ...
@@ -0,0 +1,87 @@
0
+#!/bin/bash
1
+
2
+set -e
3
+
4
+if ! git diff-index --quiet HEAD -- || test $(git ls-files --exclude-standard --others | wc -l) != 0; then
5
+  echo "You can't have any staged files in git when updating packages."
6
+  echo "Either commit them or unstage them to continue."
7
+  exit 1
8
+fi
9
+
10
+THIRD_PARTY_DIR=$(dirname $0)
11
+cd $THIRD_PARTY_DIR
12
+
13
+. ./deps.sh
14
+
15
+if [ $# -gt 0 ]; then
16
+  PACKAGES="$@"
17
+fi
18
+
19
+# Create a temp GOPATH root.  It must be an absolute path
20
+mkdir -p ../output/go_dep_update
21
+cd ../output/go_dep_update
22
+TMP_GO_ROOT=$PWD
23
+cd -
24
+export GOPATH=${TMP_GO_ROOT}
25
+
26
+for p in $PACKAGES; do
27
+  echo "Fetching $p"
28
+
29
+  # this is the target directory
30
+  mkdir -p src/$p
31
+
32
+  extra=
33
+  if [[ "$FROM_GOPATH" != "" ]]; then
34
+    extra=" (fork)"
35
+    mkdir -p "${TMP_GO_ROOT}/src/$p"
36
+    frompath="${FROM_GOPATH}/src/$p/"
37
+    cd "${frompath}"
38
+    if ! git diff-index --quiet HEAD -- || test $(git ls-files --exclude-standard --others | wc -l) != 0; then
39
+      echo "You can't have any staged files in ${frompath} git when updating packages."
40
+      echo "Either commit them or unstage them to continue."
41
+      exit 1
42
+    fi
43
+    cd -
44
+    rsync -a -z -r "${frompath}" "${TMP_GO_ROOT}/src/$p"
45
+  else
46
+    # This will checkout the project into src
47
+    if [ $p == "github.com/GoogleCloudPlatform/kubernetes" ]; then
48
+      git clone https://github.com/GoogleCloudPlatform/kubernetes.git $TMP_GO_ROOT/src/$p
49
+    else
50
+      go get -u -d $p
51
+    fi
52
+  fi
53
+
54
+  if [ $p == "github.com/GoogleCloudPlatform/kubernetes" ]; then
55
+    export GOPATH=${TMP_GO_ROOT}/src/github.com/GoogleCloudPlatform/kubernetes/third_party:${TMP_GO_ROOT}
56
+  fi
57
+
58
+  # The go get path
59
+  gp=$TMP_GO_ROOT/src/$p
60
+
61
+  # Attempt to find the commit hash of the repo
62
+  cd $gp
63
+
64
+  HEAD=
65
+  REL_PATH=$(git rev-parse --show-prefix 2>/dev/null)
66
+  if [[ -z "$HEAD" && $REL_PATH != *target/go_dep_update* ]]; then
67
+    # Grab the head if it is git
68
+    HEAD=$(git rev-parse HEAD)
69
+  fi
70
+
71
+  # Grab the head if it is mercurial
72
+  if [[ -z "$HEAD" ]] && hg root >/dev/null 2>&1; then
73
+    HEAD=$(hg id -i)
74
+  fi
75
+
76
+  cd -
77
+
78
+  # Copy the code into the final directory
79
+  rsync -a -z -r --exclude '.git/' --exclude '.hg/' $TMP_GO_ROOT/src/$p/ src/$p
80
+
81
+  # Make a nice commit about what everything bumped to
82
+  git add src/$p
83
+  if ! git diff --cached --exit-code > /dev/null 2>&1; then
84
+    git commit -m "bump(${p}): ${HEAD}${extra}"
85
+  fi
86
+done