Esempio n. 1
0
// Checks if iptables version has a "wait" flag
func getIptablesWaitFlag(vstring string) []string {
	version, err := semver.NewVersion(vstring)
	if err != nil {
		glog.Errorf("vstring (%s) is not a valid version string: %v", vstring, err)
		return nil
	}

	minVersion, err := semver.NewVersion(MinWaitVersion)
	if err != nil {
		glog.Errorf("MinWaitVersion (%s) is not a valid version string: %v", MinWaitVersion, err)
		return nil
	}
	if version.LessThan(*minVersion) {
		return nil
	}

	minVersion, err = semver.NewVersion(MinWait2Version)
	if err != nil {
		glog.Errorf("MinWait2Version (%s) is not a valid version string: %v", MinWait2Version, err)
		return nil
	}
	if version.LessThan(*minVersion) {
		return []string{"-w"}
	} else {
		return []string{"-w2"}
	}
}
Esempio n. 2
0
// UpgradeResponse upgrades an HTTP response to one that supports multiplexed
// streams. newStreamHandler will be called synchronously whenever the
// other end of the upgraded connection creates a new stream.
func (u responseUpgrader) UpgradeResponse(w http.ResponseWriter, req *http.Request, newStreamHandler httpstream.NewStreamHandler) httpstream.Connection {
	connectionHeader := strings.ToLower(req.Header.Get(httpstream.HeaderConnection))
	upgradeHeader := strings.ToLower(req.Header.Get(httpstream.HeaderUpgrade))
	if !strings.Contains(connectionHeader, strings.ToLower(httpstream.HeaderUpgrade)) || !strings.Contains(upgradeHeader, strings.ToLower(HeaderSpdy31)) {
		w.Write([]byte(fmt.Sprintf("Unable to upgrade: missing upgrade headers in request: %#v", req.Header)))
		w.WriteHeader(http.StatusBadRequest)
		return nil
	}

	hijacker, ok := w.(http.Hijacker)
	if !ok {
		w.Write([]byte("Unable to upgrade: unable to hijack response"))
		w.WriteHeader(http.StatusInternalServerError)
		return nil
	}

	w.Header().Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
	w.Header().Add(httpstream.HeaderUpgrade, HeaderSpdy31)
	w.WriteHeader(http.StatusSwitchingProtocols)

	conn, _, err := hijacker.Hijack()
	if err != nil {
		glog.Errorf("Unable to upgrade: error hijacking response: %v", err)
		return nil
	}

	spdyConn, err := NewServerConnection(conn, newStreamHandler)
	if err != nil {
		glog.Errorf("Unable to upgrade: error creating SPDY server connection: %v", err)
		return nil
	}

	return spdyConn
}
Esempio n. 3
0
func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error {
	cmd := "nsenter"
	base_args := []string{
		"--mount=/rootfs/proc/1/ns/mnt",
		"--",
	}

	echo_args := append(base_args, "sh", "-c",
		fmt.Sprintf("echo %q | cat > %s", data, filename))
	glog.V(5).Infof("Command to write data to file: %v %v", cmd, echo_args)
	outputBytes, err := exec.Command(cmd, echo_args...).CombinedOutput()
	if err != nil {
		glog.Errorf("Output from writing to %q: %v", filename, string(outputBytes))
		return err
	}

	chmod_args := append(base_args, "chmod", fmt.Sprintf("%o", perm), filename)
	glog.V(5).Infof("Command to change permissions to file: %v %v", cmd, chmod_args)
	outputBytes, err = exec.Command(cmd, chmod_args...).CombinedOutput()
	if err != nil {
		glog.Errorf("Output from chmod command: %v", string(outputBytes))
		return err
	}

	return nil
}
Esempio n. 4
0
// Checks if iptables has the "-C" flag
func getIptablesHasCheckCommand(vstring string) bool {
	minVersion, err := semver.NewVersion(MinCheckVersion)
	if err != nil {
		glog.Errorf("MinCheckVersion (%s) is not a valid version string: %v", MinCheckVersion, err)
		return true
	}
	version, err := semver.NewVersion(vstring)
	if err != nil {
		glog.Errorf("vstring (%s) is not a valid version string: %v", vstring, err)
		return true
	}
	if version.LessThan(*minVersion) {
		return false
	}
	return true
}
Esempio n. 5
0
// Writes 'value' to /proc/<pid>/oom_score_adj for all processes in cgroup cgroupName.
// Keeps trying to write until the process list of the cgroup stabilizes, or until maxTries tries.
func (oomAdjuster *OOMAdjuster) applyOOMScoreAdjContainer(cgroupName string, oomScoreAdj, maxTries int) error {
	adjustedProcessSet := make(map[int]bool)
	for i := 0; i < maxTries; i++ {
		continueAdjusting := false
		pidList, err := oomAdjuster.pidLister(cgroupName)
		if err != nil {
			continueAdjusting = true
			glog.Errorf("Error getting process list for cgroup %s: %+v", cgroupName, err)
		} else if len(pidList) == 0 {
			continueAdjusting = true
		} else {
			for _, pid := range pidList {
				if !adjustedProcessSet[pid] {
					continueAdjusting = true
					if err = oomAdjuster.ApplyOOMScoreAdj(pid, oomScoreAdj); err == nil {
						adjustedProcessSet[pid] = true
					}
				}
			}
		}
		if !continueAdjusting {
			return nil
		}
		// There's a slight race. A process might have forked just before we write its OOM score adjust.
		// The fork might copy the parent process's old OOM score, then this function might execute and
		// update the parent's OOM score, but the forked process id might not be reflected in cgroup.procs
		// for a short amount of time. So this function might return without changing the forked process's
		// OOM score. Very unlikely race, so ignoring this for now.
	}
	return fmt.Errorf("exceeded maxTries, some processes might not have desired OOM score")
}
Esempio n. 6
0
// rewriteResponse modifies an HTML response by updating absolute links referring
// to the original host to instead refer to the proxy transport.
func (t *Transport) rewriteResponse(req *http.Request, resp *http.Response) (*http.Response, error) {
	origBody := resp.Body
	defer origBody.Close()

	newContent := &bytes.Buffer{}
	var reader io.Reader = origBody
	var writer io.Writer = newContent
	encoding := resp.Header.Get("Content-Encoding")
	switch encoding {
	case "gzip":
		var err error
		reader, err = gzip.NewReader(reader)
		if err != nil {
			return nil, fmt.Errorf("errorf making gzip reader: %v", err)
		}
		gzw := gzip.NewWriter(writer)
		defer gzw.Close()
		writer = gzw
	// TODO: support flate, other encodings.
	case "":
		// This is fine
	default:
		// Some encoding we don't understand-- don't try to parse this
		glog.Errorf("Proxy encountered encoding %v for text/html; can't understand this so not fixing links.", encoding)
		return resp, nil
	}

	urlRewriter := func(targetUrl string) string {
		return t.rewriteURL(targetUrl, req.URL)
	}
	err := rewriteHTML(reader, writer, urlRewriter)
	if err != nil {
		glog.Errorf("Failed to rewrite URLs: %v", err)
		return resp, 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
}
Esempio n. 7
0
// Replace will delete the contents of 'f', using instead the given map.
// 'f' takes ownership of the map, you should not reference the map again
// after calling this function. f's queue is reset, too; upon return, it
// will contain the items in the map, in no particular order.
func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
	f.lock.Lock()
	defer f.lock.Unlock()
	for _, item := range list {
		if err := f.queueActionLocked(Sync, item); err != nil {
			return fmt.Errorf("couldn't enqueue object: %v", err)
		}
	}
	if f.knownObjectKeys == nil {
		return nil
	}

	keySet := make(sets.String, len(list))
	for _, item := range list {
		key, err := f.KeyOf(item)
		if err != nil {
			return KeyError{item, err}
		}
		keySet.Insert(key)
	}

	// Detect deletions not already in the queue.
	knownKeys := f.knownObjectKeys.ListKeys()
	for _, k := range knownKeys {
		if _, exists := keySet[k]; exists {
			continue
		}

		// This key isn't in the complete set we got, so it must have been deleted.
		if d, exists := f.items[k]; exists {
			// Don't issue a delete delta if we have one enqueued as the most
			// recent delta.
			if d.Newest().Type == Deleted {
				continue
			}
		}
		var deletedObj interface{}
		if keyGetter, ok := f.knownObjectKeys.(KeyGetter); ok {
			var exists bool
			var err error
			deletedObj, exists, err = keyGetter.GetByKey(k)
			if err != nil || !exists {
				deletedObj = nil
				if err != nil {
					glog.Errorf("Unexpected error %v during lookup of key %v, placing DeleteFinalStateUnknown marker without object", err, k)
				} else {
					glog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k)
				}
			}
		}
		if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 8
0
// logPanic logs the caller tree when a panic occurs.
func logPanic(r interface{}) {
	callers := ""
	for i := 0; true; i++ {
		_, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		callers = callers + fmt.Sprintf("%v:%v\n", file, line)
	}
	glog.Errorf("Recovered from panic: %#v (%v)\n%v", r, r, callers)
}
Esempio n. 9
0
// Close asynchronously closes all tunnels in the list after waiting for 1
// minute. Tunnels will still be open upon this function's return, but should
// no longer be used.
func (l *SSHTunnelList) Close() {
	for ix := range l.entries {
		entry := l.entries[ix]
		go func() {
			defer HandleCrash()
			time.Sleep(1 * time.Minute)
			if err := entry.Tunnel.Close(); err != nil {
				glog.Errorf("Failed to close tunnel %v: %v", entry, err)
			}
		}()
	}
}
Esempio n. 10
0
func MakeSSHTunnels(user, keyfile string, addresses []string) *SSHTunnelList {
	tunnels := []SSHTunnelEntry{}
	for ix := range addresses {
		addr := addresses[ix]
		tunnel, err := NewSSHTunnel(user, keyfile, addr)
		if err != nil {
			glog.Errorf("Failed to create tunnel for %q: %v", addr, err)
			continue
		}
		tunnels = append(tunnels, SSHTunnelEntry{addr, tunnel})
	}
	return &SSHTunnelList{tunnels}
}
Esempio n. 11
0
// Open attempts to open all tunnels in the list, and removes any tunnels that
// failed to open.
func (l *SSHTunnelList) Open() error {
	var openTunnels []SSHTunnelEntry
	for ix := range l.entries {
		if err := l.entries[ix].Tunnel.Open(); err != nil {
			glog.Errorf("Failed to open tunnel %v: %v", l.entries[ix], err)
		} else {
			openTunnels = append(openTunnels, l.entries[ix])
		}
	}
	l.entries = openTunnels
	if len(l.entries) == 0 {
		return errors.New("Failed to open any tunnels.")
	}
	return nil
}
Esempio n. 12
0
// InClusterConfig returns a config object which uses the service account
// kubernetes gives to pods. It's intended for clients that expect to be
// running inside a pod running on kuberenetes. It will return an error if
// called from a process not running in a kubernetes environment.
func InClusterConfig() (*Config, error) {
	token, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/" + api.ServiceAccountTokenKey)
	if err != nil {
		return nil, err
	}
	tlsClientConfig := TLSClientConfig{}
	rootCAFile := "/var/run/secrets/kubernetes.io/serviceaccount/" + api.ServiceAccountRootCAKey
	if _, err := util.CertPoolFromFile(rootCAFile); err != nil {
		glog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err)
	} else {
		tlsClientConfig.CAFile = rootCAFile
	}

	return &Config{
		// TODO: switch to using cluster DNS.
		Host:            "https://" + net.JoinHostPort(os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")),
		BearerToken:     string(token),
		TLSClientConfig: tlsClientConfig,
	}, nil
}
Esempio n. 13
0
func (s *SSHTunnel) copyBytes(out io.Writer, in io.Reader) {
	if _, err := io.Copy(out, in); err != nil {
		glog.Errorf("Error in SSH tunnel: %v", err)
	}
}