/
client.go
128 lines (112 loc) · 3.68 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package k8s
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"sync"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
v1cert "k8s.io/client-go/kubernetes/typed/certificates/v1"
corev1api "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/remotecommand"
)
var lock = sync.Mutex{}
var clientset kubernetes.Interface
var coreAPI corev1api.CoreV1Interface
// Allows to overwrite clientset for unittests
func SetClientset(v1 corev1api.CoreV1Interface, clset kubernetes.Interface) {
lock.Lock()
defer lock.Unlock()
coreAPI = v1
clientset = clset
}
// GetClientConfig first tries to get a config object which uses the service account kubernetes gives to pods,
// if it is called from a process running in a kubernetes environment.
// Otherwise, it tries to build config from a default kubeconfig filepath if it fails, it fallback to the default config.
// Once it get the config, it returns the same.
func getClientConfig() *rest.Config {
config, err := rest.InClusterConfig()
if err != nil {
err1 := err
kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
panic(fmt.Errorf("InClusterConfig as well as BuildConfigFromFlags Failed. Error in InClusterConfig: %+v\nError in BuildConfigFromFlags: %+v", err1, err))
}
}
return config
}
func getClientset() kubernetes.Interface {
if clientset == nil {
clientset = kubernetes.NewForConfigOrDie(getClientConfig())
}
return clientset
}
func GetClientset() kubernetes.Interface {
lock.Lock()
defer lock.Unlock()
return getClientset()
}
// GetCoreV1 first tries to get a config object which uses the service account kubernetes gives to pods,
func GetCoreV1() corev1api.CoreV1Interface {
lock.Lock()
defer lock.Unlock()
if coreAPI == nil {
coreAPI = getClientset().CoreV1()
}
return coreAPI
}
func GetV1Csr() v1cert.CertificateSigningRequestInterface {
lock.Lock()
defer lock.Unlock()
return getClientset().CertificatesV1().CertificateSigningRequests()
}
// ExecToPodThroughAPI uninterractively exec to the pod with the command specified.
// :param string command: list of the str which specify the command.
// :param string pod_name: Pod name
// :param string namespace: namespace of the Pod.
// :param io.Reader stdin: Standerd Input if necessary, otherwise `nil`
// :return: string: Output of the command. (STDOUT)
// string: Errors. (STDERR)
// error: If any error has occurred otherwise `nil`
func ExecToPodThroughAPI(command []string, containerName, podName, namespace string, stdin io.Reader) (string, string, error) {
req := GetCoreV1().RESTClient().Post().
Resource("pods").
Name(podName).
Namespace(namespace).
SubResource("exec")
scheme := runtime.NewScheme()
if err := corev1.AddToScheme(scheme); err != nil {
return "", "", fmt.Errorf("error adding to scheme: %v", err)
}
parameterCodec := runtime.NewParameterCodec(scheme)
req.VersionedParams(&corev1.PodExecOptions{
//Command: strings.Fields(command),
Command: command,
Container: containerName,
Stdin: stdin != nil,
Stdout: true,
Stderr: true,
TTY: false,
}, parameterCodec)
exec, err := remotecommand.NewSPDYExecutor(getClientConfig(), "POST", req.URL())
if err != nil {
return "", "", fmt.Errorf("error while creating Executor: %v", err)
}
var stdout, stderr bytes.Buffer
err = exec.Stream(remotecommand.StreamOptions{
Stdin: stdin,
Stdout: &stdout,
Stderr: &stderr,
Tty: false,
})
if err != nil {
return "", "", fmt.Errorf("error in Stream: %v", err)
}
return stdout.String(), stderr.String(), nil
}