// ResourceLocation returns an URL and transport which one can use to send traffic for the specified node. func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, proxyTransport http.RoundTripper, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) { schemeReq, name, portReq, valid := util.SplitSchemeNamePort(id) if !valid { return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid node request %q", id)) } nodeObj, err := getter.Get(ctx, name) if err != nil { return nil, nil, err } node := nodeObj.(*api.Node) hostIP, err := nodeutil.GetNodeHostIP(node) if err != nil { return nil, nil, err } host := hostIP.String() if portReq == "" || strconv.Itoa(ports.KubeletPort) == portReq { // Ignore requested scheme, use scheme provided by GetConnectionInfo scheme, port, kubeletTransport, err := connection.GetConnectionInfo(host) if err != nil { return nil, nil, err } return &url.URL{ Scheme: scheme, Host: net.JoinHostPort( host, strconv.FormatUint(uint64(port), 10), ), }, kubeletTransport, nil } return &url.URL{Scheme: schemeReq, Host: net.JoinHostPort(host, portReq)}, proxyTransport, nil }
// LogLocation returns the log URL for a pod container. If opts.Container is blank // and only one container is present in the pod, that container is used. func LogLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter, ctx api.Context, name string, opts *api.PodLogOptions) (*url.URL, http.RoundTripper, error) { pod, err := getPod(getter, ctx, name) if err != nil { return nil, nil, err } // Try to figure out a container // If a container was provided, it must be valid container := opts.Container if len(container) == 0 { if len(pod.Spec.Containers) == 1 { container = pod.Spec.Containers[0].Name } else { return nil, nil, errors.NewBadRequest(fmt.Sprintf("a container name must be specified for pod %s", name)) } } else { if !podHasContainerWithName(pod, container) { return nil, nil, errors.NewBadRequest(fmt.Sprintf("container %s is not valid for pod %s", container, name)) } } nodeHost := pod.Spec.NodeName if len(nodeHost) == 0 { // If pod has not been assigned a host, return an empty location return nil, nil, nil } nodeScheme, nodePort, nodeTransport, err := connInfo.GetConnectionInfo(nodeHost) if err != nil { return nil, nil, err } params := url.Values{} if opts.Follow { params.Add("follow", "true") } if opts.Previous { params.Add("previous", "true") } if opts.Timestamps { params.Add("timestamps", "true") } if opts.SinceSeconds != nil { params.Add("sinceSeconds", strconv.FormatInt(*opts.SinceSeconds, 10)) } if opts.SinceTime != nil { params.Add("sinceTime", opts.SinceTime.Format(time.RFC3339)) } if opts.TailLines != nil { params.Add("tailLines", strconv.FormatInt(*opts.TailLines, 10)) } if opts.LimitBytes != nil { params.Add("limitBytes", strconv.FormatInt(*opts.LimitBytes, 10)) } loc := &url.URL{ Scheme: nodeScheme, Host: fmt.Sprintf("%s:%d", nodeHost, nodePort), Path: fmt.Sprintf("/containerLogs/%s/%s/%s", pod.Namespace, pod.Name, container), RawQuery: params.Encode(), } return loc, nodeTransport, nil }
func streamLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter, ctx api.Context, name string, opts runtime.Object, container, path string) (*url.URL, http.RoundTripper, error) { pod, err := getPod(getter, ctx, name) if err != nil { return nil, nil, err } // Try to figure out a container // If a container was provided, it must be valid if container == "" { if len(pod.Spec.Containers) == 1 { container = pod.Spec.Containers[0].Name } else { return nil, nil, errors.NewBadRequest(fmt.Sprintf("a container name must be specified for pod %s", name)) } } else { if !podHasContainerWithName(pod, container) { return nil, nil, errors.NewBadRequest(fmt.Sprintf("container %s is not valid for pod %s", container, name)) } } nodeHost := pod.Spec.NodeName if len(nodeHost) == 0 { // If pod has not been assigned a host, return an empty location return nil, nil, errors.NewBadRequest(fmt.Sprintf("pod %s does not have a host assigned", name)) } nodeScheme, nodePort, nodeTransport, err := connInfo.GetConnectionInfo(nodeHost) if err != nil { return nil, nil, err } params := url.Values{} if err := streamParams(params, opts); err != nil { return nil, nil, err } loc := &url.URL{ Scheme: nodeScheme, Host: fmt.Sprintf("%s:%d", nodeHost, nodePort), Path: fmt.Sprintf("/%s/%s/%s/%s", path, pod.Namespace, pod.Name, container), RawQuery: params.Encode(), } return loc, nodeTransport, nil }
// PortForwardLocation returns the port-forward URL for a pod. func PortForwardLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter, ctx api.Context, name string) (*url.URL, http.RoundTripper, error) { pod, err := getPod(getter, ctx, name) if err != nil { return nil, nil, err } nodeHost := pod.Spec.NodeName if len(nodeHost) == 0 { // If pod has not been assigned a host, return an empty location return nil, nil, errors.NewBadRequest(fmt.Sprintf("pod %s does not have a host assigned", name)) } nodeScheme, nodePort, nodeTransport, err := connInfo.GetConnectionInfo(nodeHost) if err != nil { return nil, nil, err } loc := &url.URL{ Scheme: nodeScheme, Host: fmt.Sprintf("%s:%d", nodeHost, nodePort), Path: fmt.Sprintf("/portForward/%s/%s", pod.Namespace, pod.Name), } return loc, nodeTransport, nil }