github.com/percona/percona-xtradb-cluster-operator@v1.14.0/clientcmd/clientcmd.go (about) 1 package clientcmd 2 3 import ( 4 "bufio" 5 "context" 6 "io" 7 8 "github.com/pkg/errors" 9 corev1 "k8s.io/api/core/v1" 10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 "k8s.io/client-go/kubernetes/scheme" 12 corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 13 restclient "k8s.io/client-go/rest" 14 "k8s.io/client-go/tools/clientcmd" 15 "k8s.io/client-go/tools/remotecommand" 16 ) 17 18 type Client struct { 19 client corev1client.CoreV1Interface 20 restconfig *restclient.Config 21 } 22 23 func NewClient() (*Client, error) { 24 // Instantiate loader for kubeconfig file. 25 kubeconfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( 26 clientcmd.NewDefaultClientConfigLoadingRules(), 27 &clientcmd.ConfigOverrides{ 28 Timeout: "10s", 29 }, 30 ) 31 32 // Get a rest.Config from the kubeconfig file. This will be passed into all 33 // the client objects we create. 34 restconfig, err := kubeconfig.ClientConfig() 35 if err != nil { 36 return nil, err 37 } 38 39 // Create a Kubernetes core/v1 client. 40 cl, err := corev1client.NewForConfig(restconfig) 41 if err != nil { 42 return nil, err 43 } 44 45 return &Client{ 46 client: cl, 47 restconfig: restconfig, 48 }, nil 49 } 50 51 func (c *Client) PodLogs(namespace, podName string, opts *corev1.PodLogOptions) ([]string, error) { 52 logs, err := c.client.Pods(namespace).GetLogs(podName, opts).Stream(context.TODO()) 53 if err != nil { 54 return nil, errors.Wrap(err, "get pod logs stream") 55 } 56 defer logs.Close() 57 58 logArr := make([]string, 0) 59 sc := bufio.NewScanner(logs) 60 for sc.Scan() { 61 logArr = append(logArr, sc.Text()) 62 } 63 return logArr, errors.Wrap(sc.Err(), "reading logs stream") 64 } 65 66 func (c *Client) IsPodRunning(namespace, podName string) (bool, error) { 67 pod, err := c.client.Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{}) 68 if err != nil { 69 return false, err 70 } 71 72 if pod.Status.Phase != corev1.PodRunning { 73 return false, nil 74 } 75 76 for _, v := range pod.Status.Conditions { 77 if v.Type == corev1.ContainersReady && v.Status == corev1.ConditionTrue { 78 return true, nil 79 } 80 } 81 return false, nil 82 } 83 84 func (c *Client) Exec(pod *corev1.Pod, containerName string, command []string, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { 85 // Prepare the API URL used to execute another process within the Pod. In 86 // this case, we'll run a remote shell. 87 req := c.client.RESTClient(). 88 Post(). 89 Namespace(pod.Namespace). 90 Resource("pods"). 91 Name(pod.Name). 92 SubResource("exec"). 93 VersionedParams(&corev1.PodExecOptions{ 94 Container: containerName, 95 Command: command, 96 Stdin: stdin != nil, 97 Stdout: stdout != nil, 98 Stderr: stderr != nil, 99 TTY: tty, 100 }, scheme.ParameterCodec) 101 102 exec, err := remotecommand.NewSPDYExecutor(c.restconfig, "POST", req.URL()) 103 if err != nil { 104 return err 105 } 106 107 // Connect this process' std{in,out,err} to the remote shell process. 108 return exec.Stream(remotecommand.StreamOptions{ 109 Stdin: stdin, 110 Stdout: stdout, 111 Stderr: stderr, 112 Tty: tty, 113 }) 114 } 115 116 func (c *Client) REST() restclient.Interface { 117 return c.client.RESTClient() 118 }