in internal/components/setup/kind.go [426:515]
func exposePerKindService(port config.KindExposePort, timeout time.Duration, cluster *util.K8sClusterInfo,
client *rest.RESTClient, roundTripper http.RoundTripper, upgrader spdy.Upgrader, forward *kindPortForwardContext) error {
// find resource
builder := resource.NewBuilder(cluster).
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
ContinueOnError().
NamespaceParam(port.Namespace).DefaultNamespace()
builder.ResourceNames("pods", port.Resource)
obj, err := builder.Do().Object()
if err != nil {
return err
}
forwardablePod, err := polymorphichelpers.AttachablePodForObjectFn(cluster, obj, timeout)
if err != nil {
return err
}
// build port forward request
req := client.Post().
Resource("pods").
Namespace(forwardablePod.Namespace).
Name(forwardablePod.Name).
SubResource("portforward")
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, req.URL())
// build ports
ports := strings.Split(port.Port, ",")
convertedPorts := make([]*kindPort, len(ports))
exposePorts := make([]string, len(ports))
for i, p := range ports {
if convertedPorts[i], err = buildKindPort(p, obj, forwardablePod); err != nil {
return err
}
exposePorts[i] = convertedPorts[i].waitExpose
}
var stdout bytes.Buffer
var stderr bytes.Buffer
readyChannel := make(chan struct{}, 1)
forwardErrorChannel := make(chan error, 1)
forwarder, err := portforward.New(dialer, exposePorts, forward.stopChannel, readyChannel,
bufio.NewWriter(&stdout), bufio.NewWriter(&stderr))
if err != nil {
return err
}
// start forward
go func() {
if err = forwarder.ForwardPorts(); err != nil {
forwardErrorChannel <- err
}
forward.resourceFinishedChannel <- struct{}{}
}()
// wait port forward result
select {
case <-readyChannel:
exportedPorts, err1 := forwarder.GetPorts()
if err1 != nil {
return err1
}
// format: <resource>_host
resourceName := port.Resource
resourceName = strings.ReplaceAll(resourceName, "/", "_")
resourceName = strings.ReplaceAll(resourceName, "-", "_")
if err1 := exportKindEnv(fmt.Sprintf("%s_host", resourceName),
"localhost", port.Resource); err1 != nil {
return err1
}
// format: <resource>_<need_export_port>
for _, p := range exportedPorts {
for _, kp := range convertedPorts {
if int(p.Remote) == kp.realPort {
if err1 := exportKindEnv(fmt.Sprintf("%s_%s", resourceName, kp.inputPort),
fmt.Sprintf("%d", p.Local), port.Resource); err1 != nil {
return err1
}
}
}
}
case err = <-forwardErrorChannel:
return fmt.Errorf("create forward error, %s : %v", stderr.String(), err)
}
return nil
}