func exposePerKindService()

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
}