...

Source file src/github.com/redhat-developer/odo/pkg/portForward/kubeportforward/writer.go

Documentation: github.com/redhat-developer/odo/pkg/portForward/kubeportforward

     1  package kubeportforward
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"regexp"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
    12  	"github.com/fatih/color"
    13  
    14  	"github.com/redhat-developer/odo/pkg/api"
    15  	"github.com/redhat-developer/odo/pkg/libdevfile"
    16  	"github.com/redhat-developer/odo/pkg/log"
    17  
    18  	"k8s.io/klog"
    19  )
    20  
    21  type PortWriter struct {
    22  	buffer io.Writer
    23  	end    chan bool
    24  	len    int
    25  	// mapping indicates the list of endpoints open by containers
    26  	mapping       map[string][]v1alpha2.Endpoint
    27  	fwPorts       []api.ForwardedPort
    28  	customAddress string
    29  }
    30  
    31  // NewPortWriter creates a writer that will write the content in buffer,
    32  // and Wait will return after strings "Forwarding from 127.0.0.1:" has been written "len" times
    33  func NewPortWriter(buffer io.Writer, len int, mapping map[string][]v1alpha2.Endpoint, customAddress string) *PortWriter {
    34  	return &PortWriter{
    35  		buffer:        buffer,
    36  		len:           len,
    37  		end:           make(chan bool),
    38  		mapping:       mapping,
    39  		customAddress: customAddress,
    40  	}
    41  }
    42  
    43  func (o *PortWriter) Write(buf []byte) (n int, err error) {
    44  
    45  	if o.customAddress == "" {
    46  		o.customAddress = "127.0.0.1"
    47  	}
    48  	s := string(buf)
    49  	if strings.HasPrefix(s, fmt.Sprintf("Forwarding from %s", o.customAddress)) {
    50  
    51  		fwPort, err := getForwardedPort(o.mapping, s, o.customAddress)
    52  		if err == nil {
    53  			o.fwPorts = append(o.fwPorts, fwPort)
    54  		} else {
    55  			klog.V(4).Infof("unable to get forwarded port: %v", err)
    56  		}
    57  
    58  		// Also set the colour to bolded green for easier readability
    59  		fmt.Fprintf(o.buffer, " -  %s", log.SboldColor(color.FgGreen, s))
    60  		o.len--
    61  		if o.len == 0 {
    62  			o.end <- true
    63  		}
    64  	}
    65  	return len(buf), nil
    66  }
    67  
    68  func (o *PortWriter) Wait() {
    69  	<-o.end
    70  }
    71  
    72  func (o *PortWriter) GetForwardedPorts() []api.ForwardedPort {
    73  	return o.fwPorts
    74  }
    75  
    76  func getForwardedPort(mapping map[string][]v1alpha2.Endpoint, s string, address string) (api.ForwardedPort, error) {
    77  	if address == "" {
    78  		address = "127.0.0.1"
    79  	}
    80  	regex := regexp.MustCompile(fmt.Sprintf(`Forwarding from %s:([0-9]+) -> ([0-9]+)`, address))
    81  	matches := regex.FindStringSubmatch(s)
    82  	if len(matches) < 3 {
    83  		return api.ForwardedPort{}, errors.New("unable to analyze port forwarding string")
    84  	}
    85  	localPort, err := strconv.Atoi(matches[1])
    86  	if err != nil {
    87  		return api.ForwardedPort{}, err
    88  	}
    89  	remotePort, err := strconv.Atoi(matches[2])
    90  	if err != nil {
    91  		return api.ForwardedPort{}, err
    92  	}
    93  	fp := api.ForwardedPort{
    94  		LocalAddress:  address,
    95  		LocalPort:     localPort,
    96  		ContainerPort: remotePort,
    97  	}
    98  containerLoop:
    99  	for container, endpoints := range mapping {
   100  		for _, ep := range endpoints {
   101  			if ep.TargetPort == remotePort {
   102  				fp.ContainerName = container
   103  				fp.PortName = ep.Name
   104  				fp.Exposure = string(ep.Exposure)
   105  				fp.IsDebug = libdevfile.IsDebugPort(ep.Name)
   106  				fp.Protocol = string(ep.Protocol)
   107  				break containerLoop
   108  			}
   109  		}
   110  	}
   111  	return fp, nil
   112  }
   113  

View as plain text