Merge pull request #217 from brendandburns/demo

Create a proxy server using cloudcfg.  Useful for demos
pull/6/head
Daniel Smith 2014-06-24 12:01:04 -07:00
commit 568631e765
7 changed files with 114 additions and 10 deletions

View File

@ -46,6 +46,8 @@ var (
json = flag.Bool("json", false, "If true, print raw JSON for responses")
yaml = flag.Bool("yaml", false, "If true, print raw YAML for responses")
verbose = flag.Bool("verbose", false, "If true, print extra information")
proxy = flag.Bool("proxy", false, "If true, run a proxy to the api server")
www = flag.String("www", "", "If -proxy is true, use this directory to serve static files")
)
func usage() {
@ -96,11 +98,6 @@ func main() {
os.Exit(0)
}
if len(flag.Args()) < 1 {
usage()
os.Exit(1)
}
method := flag.Arg(0)
secure := true
parsedUrl, err := url.Parse(*httpServer)
if err != nil {
@ -118,6 +115,18 @@ func main() {
}
}
if *proxy {
log.Println("Starting to serve on localhost:8001")
server := cloudcfg.NewProxyServer(*www, *httpServer, auth)
log.Fatal(server.Serve())
}
if len(flag.Args()) < 1 {
usage()
os.Exit(1)
}
method := flag.Arg(0)
matchFound := executeAPIRequest(method, auth) || executeControllerRequest(method, auth)
if matchFound == false {
log.Fatalf("Unknown command %s", method)

View File

@ -6,6 +6,7 @@ LINES=$(cat "$(dirname $0)/boilerplate.txt" | wc -l)
DIFFER=$(head -$LINES "${FILE}" | diff -q - "$(dirname $0)/boilerplate.txt")
if [[ -z "${DIFFER}" ]]; then
echo "${DIFFER}"
echo "1"
exit 0
fi

View File

@ -197,7 +197,8 @@ type Status struct {
// One of: "success", "failure", "working" (for operations not yet completed)
// TODO: if "working", include an operation identifier so final status can be
// checked.
Status string `json:"status,omitempty" yaml:"status,omitempty"`
Status string `json:"status,omitempty" yaml:"status,omitempty"`
Details string `json:"details,omitempty" yaml:"details,omitempty"`
}
// Values of Status.Status

View File

@ -147,7 +147,7 @@ func (r *Request) Body(obj interface{}) *Request {
return r
}
// Format and execute the request.
// Format and xecute the request. Returns the API object received, or an error.
func (r *Request) Do() Result {
if r.err != nil {
return Result{err: r.err}

View File

@ -79,7 +79,9 @@ func Update(name string, client client.ClientInterface, updatePeriod time.Durati
return err
}
for _, pod := range podList.Items {
_, err = client.UpdatePod(pod)
// We delete the pod here, the controller will recreate it. This will result in pulling
// a new Docker image. This isn't a full "update" but its what we support for now.
err = client.DeletePod(pod.ID)
if err != nil {
return err
}

View File

@ -131,8 +131,9 @@ func TestUpdateWithPods(t *testing.T) {
}
validateAction(Action{action: "get-controller", value: "foo"}, client.actions[0], t)
validateAction(Action{action: "list-pods"}, client.actions[1], t)
validateAction(Action{action: "update-pod", value: "pod-1"}, client.actions[2], t)
validateAction(Action{action: "update-pod", value: "pod-2"}, client.actions[3], t)
// Update deletes the pods, it relies on the replication controller to replace them.
validateAction(Action{action: "delete-pod", value: "pod-1"}, client.actions[2], t)
validateAction(Action{action: "delete-pod", value: "pod-2"}, client.actions[3], t)
}
func TestUpdateNoPods(t *testing.T) {

View File

@ -0,0 +1,90 @@
/*
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.
*/
package cloudcfg
import (
"fmt"
"io/ioutil"
"net/http"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
)
type ProxyServer struct {
Host string
Auth *client.AuthInfo
Client *client.Client
}
func NewProxyServer(filebase, host string, auth *client.AuthInfo) *ProxyServer {
server := &ProxyServer{
Host: host,
Auth: auth,
Client: client.New(host, auth),
}
fileServer := &fileServer{
prefix: "/static/",
base: filebase,
}
http.Handle("/api/", server)
http.Handle("/static/", fileServer)
return server
}
// Starts the server, loops forever.
func (s *ProxyServer) Serve() error {
return http.ListenAndServe(":8001", nil)
}
func (s *ProxyServer) doError(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusInternalServerError)
w.Header().Add("Content-type", "application/json")
data, _ := api.Encode(api.Status{
Status: api.StatusFailure,
Details: fmt.Sprintf("internal error: %#v", err),
})
w.Write(data)
}
func (s *ProxyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
result := s.Client.Verb(r.Method).Path(r.URL.Path).Do()
if result.Error() != nil {
s.doError(w, result.Error())
return
}
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-type", "application/json")
data, err := result.Raw()
if err != nil {
s.doError(w, err)
return
}
w.Write(data)
}
type fileServer struct {
prefix string
base string
}
func (f *fileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
filename := r.URL.Path[len(f.prefix):]
bytes, _ := ioutil.ReadFile(f.base + filename)
w.WriteHeader(http.StatusOK)
w.Write(bytes)
}