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"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"strconv"
@ -48,6 +47,7 @@ var (
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() {
@ -98,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 {
@ -121,14 +116,17 @@ func main() {
}
if *proxy {
server := cloudcfg.ProxyServer{
Host: *httpServer,
Client: &http.Client{},
}
http.Handle("/api/", &server)
log.Fatal(http.ListenAndServe(":8001", nil))
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

@ -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

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