Esempio n. 1
0
func syncPod(namespace string, podname string) error {
	pod, err := kubeclient.Get().Pods(namespace).Get(podname)
	if err != nil {
		return err
	}
	rcname, ok := pod.Labels["managed-by"]
	if !ok {
		return fmt.Errorf("Need a `managed-by` label")
	}
	rc, err := kubeclient.Get().ReplicationControllers(namespace).Get(rcname)
	if err != nil {
		return err
	}
	nodeName := pod.Spec.NodeName
	pod.Spec = rc.Spec.Template.Spec
	pod.Spec.NodeName = nodeName
	if pod.Annotations == nil {
		pod.Annotations = make(map[string]string)
	}
	pod.Annotations["copied-from"] = rcname
	for k, v := range rc.Spec.Template.Annotations {
		if strings.HasPrefix(k, "config/") {
			pod.Annotations[k] = v
		}
	}
	_, err = kubeclient.Get().Pods(namespace).Update(pod)
	return err
}
Esempio n. 2
0
func editEndpoints(c *gin.Context) {
	namespace := c.Param("ns")
	epname := c.Param("ep")
	_, delete := c.GetQuery("delete")

	ep, err := kubeclient.Get().Endpoints(namespace).Get(epname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	b, err := json.Marshal(ep)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var out bytes.Buffer
	err = json.Indent(&out, b, "", "  ")
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "endpointsEdit", gin.H{
		"title":     epname,
		"namespace": namespace,
		"objname":   epname,
		"json":      out.String(),
		"delete":    strconv.FormatBool(delete),
	})
}
Esempio n. 3
0
func editReplicationController(c *gin.Context) {
	namespace := c.Param("ns")
	rcname := c.Param("rc")
	_, delete := c.GetQuery("delete")

	rc, err := kubeclient.Get().ReplicationControllers(namespace).Get(rcname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	b, err := json.Marshal(rc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var out bytes.Buffer
	err = json.Indent(&out, b, "", "  ")
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "replicationControllerEdit", gin.H{
		"title":     rcname,
		"namespace": namespace,
		"objname":   rcname,
		"json":      out.String(),
		"delete":    strconv.FormatBool(delete),
	})
}
Esempio n. 4
0
func editNode(c *gin.Context) {
	nodename := c.Param("no")
	_, delete := c.GetQuery("delete")

	node, err := kubeclient.Get().Nodes().Get(nodename)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	b, err := json.Marshal(node)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var out bytes.Buffer
	err = json.Indent(&out, b, "", "  ")
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "nodeEdit", gin.H{
		"title":   nodename,
		"objname": nodename,
		"json":    out.String(),
		"delete":  strconv.FormatBool(delete),
	})
}
Esempio n. 5
0
func updateReplicationControllerWithPod(c *gin.Context) {
	namespace := c.Param("ns")
	podname := c.Param("po")
	podjson := c.PostForm("json")

	var pod api.Pod
	err := json.Unmarshal([]byte(podjson), &pod)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	rcname, ok := pod.Labels["managed-by"]
	if !ok {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": "Need a `managed-by` label"})
		return
	}
	rc, err := kubeclient.Get().ReplicationControllers(namespace).Get(rcname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	nodeName := rc.Spec.Template.Spec.NodeName
	rc.Spec.Template.Spec = pod.Spec
	rc.Spec.Template.Spec.NodeName = nodeName
	if rc.Annotations == nil {
		rc.Annotations = make(map[string]string)
	}
	rc.Annotations["copied-from"] = podname
	if rc.Spec.Template.Annotations == nil {
		rc.Spec.Template.Annotations = make(map[string]string)
	}
	for k, v := range pod.Annotations {
		if strings.HasPrefix(k, "config/") {
			rc.Spec.Template.Annotations[k] = v
		}
	}
	_, err = kubeclient.Get().ReplicationControllers(namespace).Update(rc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s/pods/%s/edit", namespace, podname))
}
Esempio n. 6
0
func setPodImage(namespace string, podname string, fullImages []string) error {
	pod, err := kubeclient.Get().Pods(namespace).Get(podname)
	if err != nil {
		return err
	}

	for i, image := range fullImages {
		if image == "" {
			continue
		}
		glog.Infof("Set image of '%s/%s/%d': %s -> %s", namespace, podname, i, pod.Spec.Containers[i].Image, image)
		pod.Spec.Containers[i].Image = image
	}
	_, err = kubeclient.Get().Pods(namespace).Update(pod)
	if err != nil {
		return err
	}
	return nil
}
Esempio n. 7
0
func listOthersInNamespace(c *gin.Context) {
	namespace := c.Param("ns")

	user := c.MustGet(gin.AuthUserKey).(string)
	if user != "admin" && user != namespace {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": "Unauthorized"})
		return
	}

	rcList, err := kubeclient.Get().ReplicationControllers(namespace).List(labels.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	svcList, err := kubeclient.Get().Services(namespace).List(labels.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	epList, err := kubeclient.Get().Endpoints(namespace).List(labels.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	nodeList, err := kubeclient.Get().Nodes().List(labels.SelectorFromSet(labels.Set{
		"project": namespace,
	}), fields.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "nsInfo", gin.H{
		"refresh": 60,
		"title":   namespace,
		"ns":      namespace,
		"rcs":     genReplicationControllers(rcList),
		"svcs":    genServices(svcList),
		"eps":     genEndpoints(epList),
		"nodes":   genNodes(nodeList),
	})
}
Esempio n. 8
0
func deleteNode(c *gin.Context) {
	nodename := c.Param("no")

	err := kubeclient.Get().Nodes().Delete(nodename)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/nodes"))
}
Esempio n. 9
0
func deleteReplicationController(c *gin.Context) {
	namespace := c.Param("ns")
	rcname := c.Param("rc")

	rc, err := kubeclient.Get().ReplicationControllers(namespace).Get(rcname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	if rc.Spec.Replicas > 0 || rc.Status.Replicas > 0 {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": "Replicas must be 0"})
		return
	}
	err = kubeclient.Get().ReplicationControllers(namespace).Delete(rcname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s", namespace))
}
Esempio n. 10
0
func deleteEndpoints(c *gin.Context) {
	namespace := c.Param("ns")
	epname := c.Param("ep")

	err := kubeclient.Get().Endpoints(namespace).Delete(epname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s", namespace))
}
Esempio n. 11
0
func updateNode(c *gin.Context) {
	nodename := c.Param("no")
	nodejson := c.PostForm("json")

	var node api.Node
	err := json.Unmarshal([]byte(nodejson), &node)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	r, _ := kubeclient.Get().Nodes().Get(node.Name)
	node.ResourceVersion = r.ResourceVersion
	_, err = kubeclient.Get().Nodes().Update(&node)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/nodes/%s/edit", nodename))
}
Esempio n. 12
0
func updatePod(c *gin.Context) {
	namespace := c.Param("ns")
	podname := c.Param("po")
	podjson := c.PostForm("json")

	var pod api.Pod
	err := json.Unmarshal([]byte(podjson), &pod)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	r, _ := kubeclient.Get().Pods(namespace).Get(pod.Name)
	pod.ResourceVersion = r.ResourceVersion
	_, err = kubeclient.Get().Pods(namespace).Update(&pod)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s/pods/%s/edit", namespace, podname))
}
Esempio n. 13
0
func overview(c *gin.Context) {
	namespaces, err := kubeclient.Get().Namespaces().List(labels.Everything(), fields.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	summary := page.Summary{}
	for i := range namespaces.Items {
		namespace := namespaces.Items[i].Name
		podList, err := kubeclient.Get().Pods(namespace).List(labels.Everything(), fields.Everything())
		if err != nil {
			glog.Errorf("Can not get pods in namespace '%s': %v", namespace, err)
			continue
		}
		eventList, err := kubeclient.Get().Events(namespace).List(labels.Everything(), fields.Everything())
		if err != nil {
			glog.Errorf("Can not get events in namespace '%s': %v", namespace, err)
			eventList = &api.EventList{}
		}
		summary.Namespaces = append(summary.Namespaces, page.Namespace{
			Name:       namespace,
			PodCount:   len(podList.Items),
			EventCount: len(eventList.Items),
		})
	}
	nodeList, err := kubeclient.Get().Nodes().List(labels.Everything(), fields.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	summary.NodeCount = len(nodeList.Items)

	c.HTML(http.StatusOK, "overview", gin.H{
		"title":   "Sigma Overview",
		"summary": summary,
	})
}
Esempio n. 14
0
func startPod(namespace string, podname string, checks []bool) error {
	pod, err := kubeclient.Get().Pods(namespace).Get(podname)
	if err != nil {
		return err
	}

	for i, check := range checks {
		if pod.Spec.Containers[i].Image != PauseImage {
			// Already started.
			continue
		}
		if check {
			paused := fmt.Sprintf("paused%d", i)
			pod.Spec.Containers[i].Image = pod.Annotations[paused]
			delete(pod.Annotations, paused)
		}
	}

	_, err = kubeclient.Get().Pods(namespace).Update(pod)
	if err != nil {
		return err
	}
	return nil
}
Esempio n. 15
0
func listNodes(c *gin.Context) {
	if c.MustGet(gin.AuthUserKey).(string) != "admin" {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": "Unauthorized"})
		return
	}

	list, err := kubeclient.Get().Nodes().List(labels.Everything(), fields.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "nodeList", gin.H{
		"title": "Sigma Nodes",
		"nodes": genNodes(list),
	})
}
Esempio n. 16
0
func createService(c *gin.Context) {
	namespace := c.Param("ns")
	svcjson := c.PostForm("json")

	var svc api.Service
	err := json.Unmarshal([]byte(svcjson), &svc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	_, err = kubeclient.Get().Services(namespace).Create(&svc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s", namespace))
}
Esempio n. 17
0
func listEventsInNamespace(c *gin.Context) {
	namespace := c.Param("ns")

	user := c.MustGet(gin.AuthUserKey).(string)
	if user != "admin" && user != namespace {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": "Unauthorized"})
		return
	}

	list, err := kubeclient.Get().Events(namespace).List(labels.Everything(), fields.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "eventList", gin.H{
		"title":  "Sigma Events",
		"events": genEvents(list),
	})
}
Esempio n. 18
0
func updateEndpoints(c *gin.Context) {
	namespace := c.Param("ns")
	epname := c.Param("ep")
	epjson := c.PostForm("json")

	var ep api.Endpoints
	err := json.Unmarshal([]byte(epjson), &ep)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	_, err = kubeclient.Get().Endpoints(namespace).Update(&ep)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s/endpoints/%s/edit", namespace, epname))
}
Esempio n. 19
0
func updateReplicationController(c *gin.Context) {
	namespace := c.Param("ns")
	rcname := c.Param("rc")
	rcjson := c.PostForm("json")

	var rc api.ReplicationController
	err := json.Unmarshal([]byte(rcjson), &rc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	_, err = kubeclient.Get().ReplicationControllers(namespace).Update(&rc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s/replicationcontrollers/%s/edit", namespace, rcname))
}
Esempio n. 20
0
func createReplicationController(c *gin.Context) {
	namespace := c.Param("ns")
	rcjson := c.PostForm("json")

	var rc api.ReplicationController
	err := json.Unmarshal([]byte(rcjson), &rc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	if rc.Spec.Selector == nil {
		rc.Spec.Selector = make(map[string]string)
	}
	rc.Spec.Selector["managed-by"] = rc.Name
	if rc.Spec.Template.Labels == nil {
		rc.Spec.Template.Labels = make(map[string]string)
	}
	rc.Spec.Template.Labels["managed-by"] = rc.Name
	rc.Spec.Template.Spec.Containers[0].Name = rc.Name

	var meta api.ObjectMeta // clean metadata
	meta.Name = rc.Name
	meta.GenerateName = rc.GenerateName
	meta.Labels = rc.Labels
	meta.Annotations = rc.Annotations
	if meta.Labels != nil {
		meta.Labels["managed-by"] = rc.Name
	}
	rc.ObjectMeta = meta

	_, err = kubeclient.Get().ReplicationControllers(namespace).Create(&rc)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s", namespace))
}
Esempio n. 21
0
func describePod(c *gin.Context) {
	namespace := c.Param("ns")
	podname := c.Param("po")

	pod, err := kubeclient.Get().Pods(namespace).Get(podname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	b, err := json.Marshal(pod)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var out bytes.Buffer
	err = json.Indent(&out, b, "", "  ")
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var containers []string
	for i := range pod.Spec.Containers {
		containers = append(containers, pod.Spec.Containers[i].Name)
	}

	c.HTML(http.StatusOK, "podDetail", gin.H{
		"title":      podname,
		"namespace":  namespace,
		"pod":        podname,
		"containers": containers,
		"json":       out.String(),
	})
}
Esempio n. 22
0
func listPodsInNamespace(c *gin.Context) {
	namespace := c.Param("ns")

	user := c.MustGet(gin.AuthUserKey).(string)
	if user != "admin" && user != namespace {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": "Unauthorized"})
		return
	}

	labelSelectorString, ok := c.GetQuery("labelSelector")
	var labelSelector labels.Selector
	if !ok {
		labelSelector = labels.Everything()
	} else {
		var err error
		if labelSelector, err = labels.Parse(labelSelectorString); err != nil {
			c.HTML(http.StatusBadRequest, "error", gin.H{"error": err.Error()})
			return
		}
	}

	list, err := kubeclient.Get().Pods(namespace).List(labelSelector, fields.Everything())
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	pods := genPods(list)
	images, statuses, hosts := page.GetPodsFilters(pods)

	image, ok := c.GetQuery("image")
	if ok && len(image) > 0 {
		theImage := page.PodImage{Image: image, PrivateRepo: true}
		pods = page.FilterPodsByImage(pods, theImage)
	}

	status, ok := c.GetQuery("status")
	if ok && len(status) > 0 {
		pods = page.FilterPodsByStatus(pods, status)
	}

	host, ok := c.GetQuery("host")
	if ok && len(host) > 0 {
		pods = page.FilterPodsByHost(pods, host)
	}

	sortAlgo, ok := c.GetQuery("sort")
	if ok && len(sortAlgo) > 0 {
		switch sortAlgo {
		case "ByName":
			sort.Sort(page.ByName(pods))
		case "ByBirth":
			sort.Sort(sort.Reverse(page.ByBirth(pods)))
		default:
			sort.Sort(sort.Reverse(page.ByBirth(pods)))
		}
	} else {
		sort.Sort(sort.Reverse(page.ByBirth(pods)))
	}

	c.HTML(http.StatusOK, "podList", gin.H{
		"title":     "Sigma Pods",
		"refresh":   60,
		"namespace": namespace,
		"queries": map[string]string{
			"labelSelector": labelSelectorString,
			"image":         image,
			"status":        status,
			"host":          host,
			"sort":          sortAlgo,
		},
		"pods":     pods,
		"images":   images,
		"statuses": statuses,
		"hosts":    hosts,
	})
}
Esempio n. 23
0
func describeNode(c *gin.Context) {
	nodename := c.Param("no")

	node, err := kubeclient.Get().Nodes().Get(nodename)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	d := page.NodeDetail{
		Name:              node.Name,
		Labels:            node.Labels,
		CreationTimestamp: node.CreationTimestamp.Time.Format(time.RFC1123Z),
		Conditions:        node.Status.Conditions,
		Capacity:          kube.TranslateResourseList(node.Status.Capacity),
		SystemInfo:        node.Status.NodeInfo,
	}
	allPods, err := kubeclient.GetAllPods()
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	d.Pods = kube.FilterNodePods(allPods, node)
	d.TerminatedPods, d.NonTerminatedPods = kube.FilterTerminatedPods(d.Pods)
	d.NonTerminatedPodsResources = computePodsResources(d.NonTerminatedPods, node)
	d.TerminatedPodsResources = computePodsResources(d.TerminatedPods, node)
	d.AllocatedResources, err = computeNodeResources(d.NonTerminatedPods, node)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var pods []page.Pod
	for _, pod := range d.Pods {
		pods = append(pods, genOnePod(pod))
	}

	var nodeEvents []page.Event
	var nodeEventList *api.EventList
	if ref, err := api.GetReference(node); err != nil {
		glog.Errorf("Unable to construct reference to '%#v': %v", node, err)
	} else {
		ref.UID = types.UID(ref.Name)
		if nodeEventList, err = kubeclient.Get().Events("").Search(ref); err != nil {
			glog.Errorf("Unable to search events for '%#v': %v", node, err)
		}
	}
	if nodeEventList != nil {
		nodeEvents = genEvents(nodeEventList)
	}

	var events []page.Event
	var eventList *api.EventList
	if eventList, err = kubeclient.Get().Events("").List(labels.Everything(), fields.Everything()); err != nil {
		glog.Errorf("Unable to search events for '%#v': %v", node, err)
	}
	if eventList != nil {
		events = genEvents(&api.EventList{Items: kube.FilterEventsFromNode(eventList.Items, node)})
	}

	c.HTML(http.StatusOK, "nodeDetail", gin.H{
		"title":      nodename,
		"node":       d,
		"pods":       pods,
		"events":     events,
		"nodeEvents": nodeEvents,
	})
}
Esempio n. 24
0
func readLog(c *gin.Context, namespace string, podname string, containername string, previous bool) {
	pod, err := kubeclient.Get().Pods(namespace).Get(podname)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	var containers []string
	for i := range pod.Spec.Containers {
		containers = append(containers, pod.Spec.Containers[i].Name)
	}

	container := pod.Spec.Containers[0].Name
	if len(containername) > 0 {
		container = containername
	}
	limitBytes := int64(256 * 1024)
	tailLines := int64(500)
	logOptions := &api.PodLogOptions{
		Container:  container,
		Follow:     false,
		Previous:   previous,
		Timestamps: false,
		TailLines:  &tailLines,
		LimitBytes: &limitBytes,
	}

	req := kubeclient.Get().RESTClient.
		Get().
		Namespace(namespace).
		Name(podname).
		Resource("pods").
		SubResource("log").
		Param("container", logOptions.Container).
		Param("follow", strconv.FormatBool(logOptions.Follow)).
		Param("previous", strconv.FormatBool(logOptions.Previous)).
		Param("timestamps", strconv.FormatBool(logOptions.Timestamps)).
		Param("tailLines", strconv.FormatInt(*logOptions.TailLines, 10)).
		Param("limitBytes", strconv.FormatInt(*logOptions.LimitBytes, 10))
	readCloser, err := req.Stream()
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}
	defer readCloser.Close()

	var out bytes.Buffer
	_, err = io.Copy(&out, readCloser)
	if err != nil {
		c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()})
		return
	}

	c.HTML(http.StatusOK, "podLog", gin.H{
		"title":      podname,
		"namespace":  namespace,
		"pod":        podname,
		"containers": containers,
		"log":        out.String(),
		"previous":   strconv.FormatBool(logOptions.Previous),
	})
}