mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
remove old proxy code.
This commit is contained in:
parent
f748e2d2c5
commit
bf942e859f
@ -33,7 +33,7 @@ detect-master > /dev/null
|
|||||||
detect-minions > /dev/null
|
detect-minions > /dev/null
|
||||||
|
|
||||||
MINIONS_FILE=/tmp/minions
|
MINIONS_FILE=/tmp/minions
|
||||||
"${KUBE_ROOT}/cluster/kubecfg.sh" -template '{{range.Items}}{{.ID}}:{{end}}' list minions > ${MINIONS_FILE}
|
"${KUBE_ROOT}/cluster/kubecfg.sh" -template $'{{range.Items}}{{.ID}}\n{{end}}' list minions > ${MINIONS_FILE}
|
||||||
|
|
||||||
# On vSphere, use minion IPs as their names
|
# On vSphere, use minion IPs as their names
|
||||||
if [ "$KUBERNETES_PROVIDER" == "vsphere" ]; then
|
if [ "$KUBERNETES_PROVIDER" == "vsphere" ]; then
|
||||||
@ -46,13 +46,19 @@ for (( i=0; i<${#MINION_NAMES[@]}; i++)); do
|
|||||||
# Grep returns an exit status of 1 when line is not found, so we need the : to always return a 0 exit status
|
# Grep returns an exit status of 1 when line is not found, so we need the : to always return a 0 exit status
|
||||||
count=$(grep -c ${MINION_NAMES[i]} ${MINIONS_FILE}) || :
|
count=$(grep -c ${MINION_NAMES[i]} ${MINIONS_FILE}) || :
|
||||||
if [[ "$count" == "0" ]]; then
|
if [[ "$count" == "0" ]]; then
|
||||||
echo "Failed to find ${MINION_NAMES[i]}, cluster is probably broken."
|
echo "Failed to find ${MINION_NAMES[$i]}, cluster is probably broken."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
NAME=${MINION_NAMES[i]}
|
||||||
|
if [ "$KUBERNETES_PROVIDER" != "vsphere" ]; then
|
||||||
|
# Grab fully qualified name
|
||||||
|
NAME=$(grep "${MINION_NAMES[i]}" ${MINIONS_FILE})
|
||||||
|
fi
|
||||||
|
|
||||||
# Make sure the kubelet is healthy
|
# Make sure the kubelet is healthy
|
||||||
curl_output=$(curl -s --insecure --user "${KUBE_USER}:${KUBE_PASSWORD}" \
|
curl_output=$(curl -s --insecure --user "${KUBE_USER}:${KUBE_PASSWORD}" \
|
||||||
"https://${KUBE_MASTER_IP}/proxy/minion/${MINION_NAMES[$i]}/healthz")
|
"https://${KUBE_MASTER_IP}/api/v1beta1/proxy/minions/${NAME}/healthz")
|
||||||
if [[ "${curl_output}" != "ok" ]]; then
|
if [[ "${curl_output}" != "ok" ]]; then
|
||||||
echo "Kubelet failed to install on ${MINION_NAMES[$i]}. Your cluster is unlikely to work correctly."
|
echo "Kubelet failed to install on ${MINION_NAMES[$i]}. Your cluster is unlikely to work correctly."
|
||||||
echo "Please run ./cluster/kube-down.sh and re-create the cluster. (sorry!)"
|
echo "Please run ./cluster/kube-down.sh and re-create the cluster. (sorry!)"
|
||||||
|
@ -121,7 +121,6 @@ func (g *APIGroup) InstallREST(mux mux, paths ...string) {
|
|||||||
// InstallSupport registers the APIServer support functions into a mux.
|
// InstallSupport registers the APIServer support functions into a mux.
|
||||||
func InstallSupport(mux mux) {
|
func InstallSupport(mux mux) {
|
||||||
healthz.InstallHandler(mux)
|
healthz.InstallHandler(mux)
|
||||||
mux.Handle("/proxy/minion/", http.StripPrefix("/proxy/minion", http.HandlerFunc(handleProxyMinion)))
|
|
||||||
mux.HandleFunc("/version", handleVersion)
|
mux.HandleFunc("/version", handleVersion)
|
||||||
mux.HandleFunc("/", handleIndex)
|
mux.HandleFunc("/", handleIndex)
|
||||||
}
|
}
|
||||||
|
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
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 apiserver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.google.com/p/go.net/html"
|
|
||||||
"code.google.com/p/go.net/html/atom"
|
|
||||||
"github.com/golang/glog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: replace with proxy handler on minions
|
|
||||||
func handleProxyMinion(w http.ResponseWriter, req *http.Request) {
|
|
||||||
path := strings.TrimLeft(req.URL.Path, "/")
|
|
||||||
rawQuery := req.URL.RawQuery
|
|
||||||
|
|
||||||
// Expect path as: ${minion}/${query_to_minion}
|
|
||||||
// and query_to_minion can be any query that kubelet will accept.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// To query stats of a minion or a pod or a container,
|
|
||||||
// path string can be ${minion}/stats/<podid>/<containerName> or
|
|
||||||
// ${minion}/podInfo?podID=<podid>
|
|
||||||
//
|
|
||||||
// To query logs on a minion, path string can be:
|
|
||||||
// ${minion}/logs/
|
|
||||||
parts := strings.SplitN(path, "/", 2)
|
|
||||||
if len(parts) != 2 {
|
|
||||||
badGatewayError(w, req)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
minionHost := parts[0]
|
|
||||||
_, port, _ := net.SplitHostPort(minionHost)
|
|
||||||
if port == "" {
|
|
||||||
// Couldn't retrieve port information
|
|
||||||
// TODO: Retrieve port info from a common object
|
|
||||||
minionHost += ":10250"
|
|
||||||
}
|
|
||||||
minionPath := "/" + parts[1]
|
|
||||||
|
|
||||||
minionURL := &url.URL{
|
|
||||||
Scheme: "http",
|
|
||||||
Host: minionHost,
|
|
||||||
}
|
|
||||||
newReq, err := http.NewRequest("GET", minionPath+"?"+rawQuery, nil)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to create request: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy := httputil.NewSingleHostReverseProxy(minionURL)
|
|
||||||
proxy.Transport = &minionTransport{}
|
|
||||||
proxy.ServeHTTP(w, newReq)
|
|
||||||
}
|
|
||||||
|
|
||||||
type minionTransport struct{}
|
|
||||||
|
|
||||||
func (t *minionTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
||||||
resp, err := http.DefaultTransport.RoundTrip(req)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "connection refused") {
|
|
||||||
message := fmt.Sprintf("Failed to connect to minion:%s", req.URL.Host)
|
|
||||||
resp = &http.Response{
|
|
||||||
StatusCode: http.StatusServiceUnavailable,
|
|
||||||
Body: ioutil.NopCloser(strings.NewReader(message)),
|
|
||||||
}
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(resp.Header.Get("Content-Type"), "text/plain") {
|
|
||||||
// Do nothing, simply pass through
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err = t.ProcessResponse(req, resp)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *minionTransport) ProcessResponse(req *http.Request, resp *http.Response) (*http.Response, error) {
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
// copying the response body did not work
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
bodyNode := &html.Node{
|
|
||||||
Type: html.ElementNode,
|
|
||||||
Data: "body",
|
|
||||||
DataAtom: atom.Body,
|
|
||||||
}
|
|
||||||
nodes, err := html.ParseFragment(bytes.NewBuffer(body), bodyNode)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to found <body> node: %v", err)
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the method to traverse the doc tree and update href node to
|
|
||||||
// point to correct minion
|
|
||||||
var updateHRef func(*html.Node)
|
|
||||||
updateHRef = func(n *html.Node) {
|
|
||||||
if n.Type == html.ElementNode && n.Data == "a" {
|
|
||||||
for i, attr := range n.Attr {
|
|
||||||
if attr.Key == "href" {
|
|
||||||
Url := &url.URL{
|
|
||||||
Path: "/proxy/minion/" + req.URL.Host + req.URL.Path + attr.Val,
|
|
||||||
}
|
|
||||||
n.Attr[i].Val = Url.String()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
||||||
updateHRef(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newContent := &bytes.Buffer{}
|
|
||||||
for _, n := range nodes {
|
|
||||||
updateHRef(n)
|
|
||||||
err = html.Render(newContent, n)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to render: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Body = ioutil.NopCloser(newContent)
|
|
||||||
// Update header node with new content-length
|
|
||||||
// TODO: Remove any hash/signature headers here?
|
|
||||||
resp.Header.Del("Content-Length")
|
|
||||||
resp.ContentLength = int64(newContent.Len())
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
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 apiserver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMinionTransport(t *testing.T) {
|
|
||||||
content := string(`<pre><a href="kubelet.log">kubelet.log</a><a href="google.log">google.log</a></pre>`)
|
|
||||||
transport := &minionTransport{}
|
|
||||||
|
|
||||||
// Test /logs/
|
|
||||||
request := &http.Request{
|
|
||||||
Method: "GET",
|
|
||||||
URL: &url.URL{
|
|
||||||
Scheme: "http",
|
|
||||||
Host: "minion1:10250",
|
|
||||||
Path: "/logs/",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
response := &http.Response{
|
|
||||||
Status: "200 OK",
|
|
||||||
StatusCode: http.StatusOK,
|
|
||||||
Body: ioutil.NopCloser(strings.NewReader(content)),
|
|
||||||
Close: true,
|
|
||||||
}
|
|
||||||
updated_resp, _ := transport.ProcessResponse(request, response)
|
|
||||||
body, _ := ioutil.ReadAll(updated_resp.Body)
|
|
||||||
expected := string(`<pre><a href="/proxy/minion/minion1:10250/logs/kubelet.log">kubelet.log</a><a href="/proxy/minion/minion1:10250/logs/google.log">google.log</a></pre>`)
|
|
||||||
if !strings.Contains(string(body), expected) {
|
|
||||||
t.Errorf("Received wrong content: %s", string(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test subdir under /logs/
|
|
||||||
request = &http.Request{
|
|
||||||
Method: "GET",
|
|
||||||
URL: &url.URL{
|
|
||||||
Scheme: "http",
|
|
||||||
Host: "minion1:8080",
|
|
||||||
Path: "/whatever/apt/",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
response = &http.Response{
|
|
||||||
Status: "200 OK",
|
|
||||||
StatusCode: http.StatusOK,
|
|
||||||
Body: ioutil.NopCloser(strings.NewReader(content)),
|
|
||||||
Close: true,
|
|
||||||
}
|
|
||||||
updated_resp, _ = transport.ProcessResponse(request, response)
|
|
||||||
body, _ = ioutil.ReadAll(updated_resp.Body)
|
|
||||||
expected = string(`<pre><a href="/proxy/minion/minion1:8080/whatever/apt/kubelet.log">kubelet.log</a><a href="/proxy/minion/minion1:8080/whatever/apt/google.log">google.log</a></pre>`)
|
|
||||||
if !strings.Contains(string(body), expected) {
|
|
||||||
t.Errorf("Received wrong content: %s", string(body))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMinionProxy(t *testing.T) {
|
|
||||||
proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
w.Write([]byte(req.URL.Path))
|
|
||||||
}))
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(handleProxyMinion))
|
|
||||||
//client := http.Client{}
|
|
||||||
proxy, _ := url.Parse(proxyServer.URL)
|
|
||||||
|
|
||||||
testCases := map[string]string{
|
|
||||||
fmt.Sprintf("/%s/", proxy.Host): "/",
|
|
||||||
fmt.Sprintf("/%s/test", proxy.Host): "/test",
|
|
||||||
}
|
|
||||||
|
|
||||||
for value, expected := range testCases {
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s%s", server.URL, value))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error for %s: %v", value, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
t.Errorf("expected successful request for %s: %#v", value, resp)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
actual, _ := bufio.NewReader(resp.Body).ReadString('\n')
|
|
||||||
if actual != expected {
|
|
||||||
t.Errorf("expected %s to become %s, got %s", value, expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
failureCases := map[string]string{
|
|
||||||
"": "",
|
|
||||||
fmt.Sprintf("/%s", proxy.Host): "/",
|
|
||||||
}
|
|
||||||
|
|
||||||
for value := range failureCases {
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s%s", server.URL, value))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error for %s: %v", value, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusBadGateway {
|
|
||||||
t.Errorf("expected bad gateway response for %s: %#v", value, resp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApiServerMinionProxy(t *testing.T) {
|
|
||||||
proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
w.Write([]byte(req.URL.Path))
|
|
||||||
}))
|
|
||||||
server := httptest.NewServer(Handle(nil, nil, "/prefix", selfLinker))
|
|
||||||
proxy, _ := url.Parse(proxyServer.URL)
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s/proxy/minion/%s%s", server.URL, proxy.Host, "/test"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
t.Fatalf("expected successful request, got %#v", resp)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
actual, _ := bufio.NewReader(resp.Body).ReadString('\n')
|
|
||||||
if actual != "/test" {
|
|
||||||
t.Errorf("unexpected response body %s", actual)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user