func()

in istioctl/cmd/kubeinject.go [78:204]


func (e ExternalInjector) Inject(pod *corev1.Pod, deploymentNS string) ([]byte, error) {
	cc := e.clientConfig
	if cc == nil {
		return nil, nil
	}
	var address string
	if cc.URL != nil {
		address = *cc.URL
	}
	var certPool *x509.CertPool
	if len(cc.CABundle) > 0 {
		certPool = x509.NewCertPool()
		certPool.AppendCertsFromPEM(cc.CABundle)
	} else {
		var err error
		certPool, err = x509.SystemCertPool()
		if err != nil {
			return nil, err
		}
	}
	tlsClientConfig := &tls.Config{RootCAs: certPool}
	client := http.Client{
		Timeout: time.Second * 5,
		Transport: &http.Transport{
			TLSClientConfig: tlsClientConfig,
		},
	}
	if cc.Service != nil {
		svc, err := e.client.CoreV1().Services(cc.Service.Namespace).Get(context.Background(), cc.Service.Name, metav1.GetOptions{})
		if err != nil {
			return nil, err
		}
		namespace, selector, err := polymorphichelpers.SelectorsForObject(svc)
		if err != nil {
			if e.injectorAddress == "" {
				return nil, fmt.Errorf("cannot attach to %T: %v", svc, err)
			}
			address = fmt.Sprintf("https://%s:%d%s", e.injectorAddress, *cc.Service.Port, *cc.Service.Path)
		} else {
			pod, err := GetFirstPod(e.client.CoreV1(), namespace, selector.String())
			if err != nil {
				return nil, err
			}
			webhookPort := cc.Service.Port
			podPort := 15017
			for _, v := range svc.Spec.Ports {
				if v.Port == *webhookPort {
					podPort = v.TargetPort.IntValue()
					break
				}
			}
			f, err := e.client.NewPortForwarder(pod.Name, pod.Namespace, "", 0, podPort)
			if err != nil {
				return nil, err
			}
			if err := f.Start(); err != nil {
				return nil, err
			}
			address = fmt.Sprintf("https://%s%s", f.Address(), *cc.Service.Path)
			defer func() {
				f.Close()
				f.WaitForStop()
			}()
		}
		tlsClientConfig.ServerName = fmt.Sprintf("%s.%s.%s", cc.Service.Name, cc.Service.Namespace, "svc")
	} else if isMCPAddr(address) {
		var err error
		client.Transport, err = mcpTransport(context.TODO(), client.Transport)
		if err != nil {
			return nil, err
		}
	}
	podBytes, err := json.Marshal(pod)
	if pod.Namespace != "" {
		deploymentNS = pod.Namespace
	}
	if err != nil {
		return nil, err
	}
	rev := &admission.AdmissionReview{
		TypeMeta: metav1.TypeMeta{
			APIVersion: admission.SchemeGroupVersion.String(),
			Kind:       "AdmissionReview",
		},
		Request: &admission.AdmissionRequest{
			Object: runtime.RawExtension{Raw: podBytes},
			Kind: metav1.GroupVersionKind{
				Group:   admission.GroupName,
				Version: admission.SchemeGroupVersion.Version,
				Kind:    "AdmissionRequest",
			},
			Resource:           metav1.GroupVersionResource{},
			SubResource:        "",
			RequestKind:        nil,
			RequestResource:    nil,
			RequestSubResource: "",
			Name:               pod.Name,
			Namespace:          deploymentNS,
		},
		Response: nil,
	}
	revBytes, err := json.Marshal(rev)
	if err != nil {
		return nil, err
	}
	resp, err := client.Post(address, "application/json", bytes.NewBuffer(revBytes))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	var obj runtime.Object
	var ar *kube.AdmissionReview
	out, _, err := deserializer.Decode(body, nil, obj)
	if err != nil {
		return nil, fmt.Errorf("could not decode body: %v", err)
	}
	ar, err = kube.AdmissionReviewKubeToAdapter(out)
	if err != nil {
		return nil, fmt.Errorf("could not decode object: %v", err)
	}

	return ar.Response.Patch, nil
}