Update the proxy server.

This commit is contained in:
Brendan Burns 2014-06-23 22:18:14 -07:00
parent 5756189f0d
commit 8b50e45dcc
6 changed files with 74 additions and 31 deletions

View File

@ -21,7 +21,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http"
"net/url" "net/url"
"os" "os"
"strconv" "strconv"
@ -48,6 +47,7 @@ var (
yaml = flag.Bool("yaml", false, "If true, print raw YAML for responses") yaml = flag.Bool("yaml", false, "If true, print raw YAML for responses")
verbose = flag.Bool("verbose", false, "If true, print extra information") verbose = flag.Bool("verbose", false, "If true, print extra information")
proxy = flag.Bool("proxy", false, "If true, run a proxy to the api server") 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() { func usage() {
@ -98,11 +98,6 @@ func main() {
os.Exit(0) os.Exit(0)
} }
if len(flag.Args()) < 1 {
usage()
os.Exit(1)
}
method := flag.Arg(0)
secure := true secure := true
parsedUrl, err := url.Parse(*httpServer) parsedUrl, err := url.Parse(*httpServer)
if err != nil { if err != nil {
@ -121,13 +116,16 @@ func main() {
} }
if *proxy { if *proxy {
server := cloudcfg.ProxyServer{ log.Println("Starting to serve on localhost:8001")
Host: *httpServer, server := cloudcfg.NewProxyServer(*www, *httpServer, auth)
Client: &http.Client{}, log.Fatal(server.Serve())
} }
http.Handle("/api/", &server)
log.Fatal(http.ListenAndServe(":8001", nil)) if len(flag.Args()) < 1 {
usage()
os.Exit(1)
} }
method := flag.Arg(0)
matchFound := executeAPIRequest(method, auth) || executeControllerRequest(method, auth) matchFound := executeAPIRequest(method, auth) || executeControllerRequest(method, auth)
if matchFound == false { if matchFound == false {

View File

@ -198,6 +198,7 @@ type Status struct {
// TODO: if "working", include an operation identifier so final status can be // TODO: if "working", include an operation identifier so final status can be
// checked. // 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 // Values of Status.Status

View File

@ -147,7 +147,7 @@ func (r *Request) Body(obj interface{}) *Request {
return r 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 { func (r *Request) Do() Result {
if r.err != nil { if r.err != nil {
return Result{err: r.err} return Result{err: r.err}

View File

@ -79,7 +79,9 @@ func Update(name string, client client.ClientInterface, updatePeriod time.Durati
return err return err
} }
for _, pod := range podList.Items { 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 { if err != nil {
return err 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: "get-controller", value: "foo"}, client.actions[0], t)
validateAction(Action{action: "list-pods"}, client.actions[1], t) validateAction(Action{action: "list-pods"}, client.actions[1], t)
validateAction(Action{action: "update-pod", value: "pod-1"}, client.actions[2], t) // Update deletes the pods, it relies on the replication controller to replace them.
validateAction(Action{action: "update-pod", value: "pod-2"}, client.actions[3], t) 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) { func TestUpdateNoPods(t *testing.T) {

View File

@ -17,33 +17,74 @@ limitations under the License.
package cloudcfg package cloudcfg
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
) )
type ProxyServer struct { type ProxyServer struct {
Host string Host string
Client *http.Client 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) { func (s *ProxyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
req, err := http.NewRequest(r.Method, s.Host+r.URL.Path, r.Body) result := s.Client.Verb(r.Method).Path(r.URL.Path).Do()
if err != nil { if result.Error() != nil {
log.Printf("Error: %#v", err) s.doError(w, result.Error())
return return
} }
res, err := s.Client.Do(req) w.WriteHeader(http.StatusOK)
w.Header().Add("Content-type", "application/json")
data, err := result.Raw()
if err != nil { if err != nil {
log.Printf("Error: %#v", err) s.doError(w, err)
return
}
w.WriteHeader(res.StatusCode)
defer res.Body.Close()
data, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Printf("Error: %#v", err)
return return
} }
w.Write(data) 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)
}